Otimização de animação Openlayer animate

1. O problema surge

O problema é simples. A empresa deve fazer um requerimento para localizar a função de vôo, ou seja, clicar no local para obter a latitude e longitude, uma animação de vôo, e voar até o ponto e nível alvo. Quando recebi essa demanda, pensei comigo mesmo, é simples. Verifique a API OpenLayer diretamente. Encontrei essa função:

view.animate(var_args)

Então, caí na minha mão e derrubei este código:

//获取目标定位点等函数省略
this.map.getView().animate({
    
    center: center, zoom: 13}) // 同时移动和放大

Aliás. Observe que os parâmetros são diferentes, o desempenho também é diferente.

  • 同时配置了center和zoom, Então o desempenho é mover e zoom ao mesmo tempo.
  • 先配置center,再配置zoom, Então a performance é panorâmica primeiro, depois zoom
  • 反之,先配置zoom,再配置center, O desempenho é o zoom primeiro, depois a panorâmica

Aí vem o problema:
Insira a descrição da imagem aqui

Está certo. A panorâmica muito rápida entre as regiões fará com que os blocos sejam carregados e não acompanhe a velocidade de movimento da tela, resultando em uma experiência do usuário ruim.

2. Análise do problema:

Isso pode ser resolvido primeiro esticando o ângulo de visão, depois fazendo uma panorâmica e depois ampliando o ângulo de visão. Portanto, temos este trecho de código:

this.map.getView().animate({
    
    zoom: 7,duration:2000}, {
    
    center: center,duration:2000},{
    
    zoom:13,duration:3000});

Rugido. É realmente perfeito para cenas interregionais.

Insira a descrição da imagem aqui

Contudo. É realmente nojento localizar um local próximo.

Insira a descrição da imagem aqui

Corrigir. Mesmo se estiver próximo, estique e aplique zoom novamente. Isso é muito desconfortável. . .

Três, resolução de problemas

Vá diretamente para o código. O mesmo fluxo de processamento, mas algoritmo otimizado. Encapsula uma smooth_animatefunção. O principal é determinar internamente a distância entre o ponto central atual e o ponto central de destino e, em seguida, calcular um zoom estendido definindo a velocidade de carregamento do bloco e realizar operações de tradução sem afetar o carregamento do bloco . 3 itens de configuração são abertos.

  • load_speed: 4, // - Vários blocos podem ser carregados em um segundo, quanto melhor for o servidor, maior será o valor
  • move_time_limit: 3, // - O tempo de tradução deve estar dentro de 3s
  • level_change_time: 200 // - Quantos milissegundos leva para aumentar um nível
import * as turf from '@turf/turf';
/**
 * 地图视角由一个地方缓缓转向另外一个地方.
 * 主要原理是计算瓦片距离,控制拉升到某个层级进行平移,达到瓦片能够在这个层级平移的时候,加载速度跟得上平移速度
 * @param {ol.Map} map 
 * @param {Array[lon,lat]} target_location  目标的经纬度
 * @param {Number} target_zoom  目标的层级
 * @param {Object} options  
 * @author daiyujie
 *      load_speed:4,    //--一秒钟可以加载几张瓦片
 *		move_time_limit:3, //--平移时间必须在3s以内
 *		level_change_time: 200 //--拉升一级(缩放一级)需要多少毫秒
 */
export const smooth_animate = function(map,target_location,target_zoom,options){
    
    

	var defaults = {
    
    
		load_speed:4,    //--一秒钟可以加载几张瓦片
		move_time_limit:3, //--平移时间必须在3s以内
		level_change_time: 200 //--拉升一级(缩放一级)需要多少毫秒
	}

	var opts = Object.assign({
    
    }, defaults, options || {
    
    });
	var view = map.getView();
	var cur_zoom =  view.getZoom();
	var cur_center=  view.getCenter();
	var min_zoom = Math.min(cur_zoom,target_zoom);
	var distance = turf.distance(cur_center,target_location);

	var pull_up_zoom = min_zoom;
	var max_tile_num = opts.load_speed * opts.move_time_limit;
	//--核心逻辑在这里
	while(view.getResolutionForZoom(pull_up_zoom)*256*max_tile_num*100 < distance){
    
    
		pull_up_zoom--;
	}
	
	var pull_up_subs_zoom = cur_zoom - pull_up_zoom;
	var duration_pull_up = pull_up_subs_zoom * opts.level_change_time;

	var pull_down_subs_zoom = target_zoom -  pull_up_zoom;
	var duration_pull_down = pull_down_subs_zoom * opts.level_change_time;
	
	view.animate(
	{
    
    
		zoom:pull_up_zoom,
		duration:duration_pull_up
	},
	{
    
    
		center: target_location,
		duration:opts.move_time_limit*1000
	},
	{
    
    
		zoom:target_zoom,
		duration:duration_pull_down
	},
	)
	return new Promise((resolve, reject) => {
    
    
		setTimeout(() => {
    
    
			resolve();
		},duration_pull_down+duration_pull_up+opts.move_time_limit*1000 + 100)
	})
	
}

Após usar a função acima, para a transferência de local na mesma distância, a operação de primeiro zoom e depois zoom não será realizada, pois o zoom calculado é igual a target_zoom.

Acho que você gosta

Origin blog.csdn.net/qq_29722281/article/details/103834483
Recomendado
Clasificación