Optimización de animación animada de capa abierta

1. Surge el problema

El problema es simple. La empresa tiene que hacer un requisito para ubicar la función de vuelo, es decir, hacer clic en la ubicación para obtener la latitud y la longitud, una animación de vuelo y volar al punto y nivel de destino. Cuando recibí esta demanda, pensé para mí mismo, es simple. Verifique la API de OpenLayer directamente. Encontré una función de este tipo:

view.animate(var_args)

Así que caí en mi mano y derribé este código:

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

De paso. Tenga en cuenta que los parámetros son diferentes, el rendimiento también es diferente.

  • 同时配置了center和zoom, Entonces la actuación es moverse y hacer zoom al mismo tiempo.
  • 先配置center,再配置zoom, Luego, la actuación consiste en desplazarse primero, luego hacer zoom
  • 反之,先配置zoom,再配置center, El rendimiento es hacer zoom primero, luego desplazarse

Aquí viene el problema:
Inserte la descripción de la imagen aquí

Así es. Una panorámica demasiado rápida entre regiones hará que los mosaicos se carguen y no sigan el ritmo de movimiento de la pantalla, lo que provocará una mala experiencia del usuario.

2. Análisis de problemas:

Se puede resolver estirando primero el ángulo de visión, luego haciendo una panorámica y luego haciendo zoom en el ángulo de visión. Entonces tenemos este fragmento de código:

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

Rugido. Es realmente perfecto para escenas interregionales.

Inserte la descripción de la imagen aquí

sin embargo. Es realmente repugnante ubicar un lugar cercano.

Inserte la descripción de la imagen aquí

Correcto. Incluso si está cerca, estírate y haz zoom nuevamente. Esto se siente realmente incómodo. . .

Tres, resolución de problemas

Vaya directamente al código. El mismo flujo de procesamiento, pero algoritmo optimizado. Encapsula una smooth_animatefunción. El núcleo es determinar internamente la distancia entre el punto central actual y el punto central del objetivo, y luego calcular un zoom extendido configurando la velocidad de carga del mosaico y realizar operaciones de traducción sin afectar la carga del mosaico . Se abren 3 elementos de configuración.

  • load_speed: 4, // - Se pueden cargar varios mosaicos en un segundo, cuanto mejor sea el servidor, mayor puede ser este valor
  • move_time_limit: 3, // - El tiempo de traducción debe ser de 3 s
  • level_change_time: 200 // - Cuántos milisegundos se necesitan para escalar un nivel (escalar un nivel)
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)
	})
	
}

Después de usar la función anterior, para la transferencia de ubicación a la misma distancia, no se realizará la operación de primer zoom y luego zoom, porque el zoom calculado es igual a target_zoom.

Supongo que te gusta

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