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:
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.
Contudo. É realmente nojento localizar um local próximo.
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_animate
funçã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 valormove_time_limit
: 3, // - O tempo de tradução deve estar dentro de 3slevel_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.