Javascript 如何在OpenLayers中的两个遥远多边形之间创建飞行动画

Javascript 如何在OpenLayers中的两个遥远多边形之间创建飞行动画,javascript,animation,openlayers,openlayers-5,openlayers-6,Javascript,Animation,Openlayers,Openlayers 5,Openlayers 6,使用Openlayers(v6.1.1.)我试图在几个多边形之间创建简单的FlyTo动画。当它们之间的距离很小时,FlyTo动画效果很好,但随着距离的增加,用户体验会减少 在更大的距离上,我只是看到在低缩放下快速平移地图。我试着回答,但没有达到预期效果 按照说明,我将一个中心动画与两个缩放动画相结合,并同时启动它们。 例如: 当多边形在附近时,此FlyTo动画效果很好,但随着距离的增加,FlyTo动画正在转换为在地图上快速平移 我创建了一个用于测试的小应用程序。 当我们单击列表项时,地图将动画化

使用Openlayers(v6.1.1.)我试图在几个多边形之间创建简单的FlyTo动画。当它们之间的距离很小时,FlyTo动画效果很好,但随着距离的增加,用户体验会减少

在更大的距离上,我只是看到在低缩放下快速平移地图。我试着回答,但没有达到预期效果

按照说明,我将一个中心动画与两个缩放动画相结合,并同时启动它们。 例如:

当多边形在附近时,此FlyTo动画效果很好,但随着距离的增加,FlyTo动画正在转换为在地图上快速平移

我创建了一个用于测试的小应用程序。 当我们单击列表项时,地图将动画化并缩放到单击的字段。例如,当awesome、另一个和super字段在附近时,FlyTo动画按预期工作,但当我们从super单击到epic字段(在遥远的南方。然后地图只是快速平移到位置)时

所以,我的问题是。是否可以独立于多边形位置为多边形实现相同的FlyTo效果(传单中有这一巧妙设置)

以下是JSFIDLE示例:

我认为您需要对缩放方式进行更多改进。例如,缩小到足以使起点和终点在峰值高度都可见。可以通过计算距离并除以贴图宽度来实现。对总体上下变化的持续时间进行一些调整,但不要太多,并按比例划分上下持续时间。要缩短初始持续时间,如果当前分辨率已大于计算的峰值高度分辨率,则持续时间的100%应向下,并且还应通过将地图拟合到矢量源范围来打开靠近要素所在位置的地图


我不确定你到底需要什么?是否需要在较大距离内降低飞行速度?如果需要增加时间(降低动画速度),则应编写另一种方法来计算时间。将当前中心减去多边形中心,然后乘以某个系数。因此,动态动画时间可以解决您的问题problem@MahdiMahmoodian随着多边形距离的增加,贴图不会缩小。它只是在地图上快速平移。我想缩小,然后再放大。谢谢你的回答,但我相信时间不是问题,我相信问题在于zoomI检查了GitHub中的源代码。“动画”功能更改更瘦系数中的缩放。这意味着在每一帧中增加/减少一点缩放。所以我认为你不能用常规的方式使用动画。也许您应该将动画分割成一些部分,并在每个减少/增加缩放中,就像您在两个阶段中所做的那样。您可以为此编写一个方法。我认为您需要对缩放方式进行更多改进。例如,缩小到足以使起点和终点在峰值高度都可见。可以通过计算距离并除以贴图宽度来实现。针对整体上下变化对持续时间进行一些调整,但不要太多,并按比例划分上下持续时间谢谢您提供了非常精确和详细的答案
let view = map.getView();
let extentOfPolygon = feature.getGeometry().getExtent();
let resolution = view.getResolutionForExtent(extentOfPolygon);
let zoom = view.getZoomForResolution(resolution);
let center = ol.extent.getCenter(extentOfPolygon);

view.animate({
  center: center,
  duration: duration
});
view.animate({
  zoom: zoom - 1,
  duration: duration / 2
}, {
  zoom: zoom,
  duration: duration / 2
});
let geojsonData = new ol.format.GeoJSON().readFeatures(fieldData, {
  featureProjection: 'EPSG:3857'
});
let vectorSource = new ol.source.Vector({
  features: geojsonData
});

let vectorLayer = new ol.layer.Vector({
  source: vectorSource
});

var map = new ol.Map({
  target: 'map',
  layers: [
    new ol.layer.Tile({
      source: new ol.source.OSM()
    }),
    vectorLayer
  ],
  view: new ol.View({
    center: [0, 0],
    zoom: 4
  })
});

map.getView().fit(vectorSource.getExtent());

const duration = 2000;

var featureListElement = document.getElementById("vectorFeatures");

var features = vectorLayer.getSource().getFeatures();
for (let feature of features) {
  let aElement = document.createElement("a");
  aElement.classList.add("list-group-item", "list-group-item-action");
  featureListElement.appendChild(aElement);
  aElement.innerHTML = feature.get("Name");
  aElement.onclick = function() {

    let view = map.getView();
    var extentOfPolygon = feature.getGeometry().getExtent();
    let resolution = view.getResolutionForExtent(extentOfPolygon);
    var center = ol.extent.getCenter(extentOfPolygon);
    var currentCenter = map.getView().getCenter();
    var currentResolution = map.getView().getResolution();
    var distance = Math.sqrt(Math.pow(center[0] - currentCenter[0], 2) + Math.pow(center[1] - currentCenter[1], 2));
    var maxResolution = Math.max(distance/ map.getSize()[0], currentResolution);
    var up = Math.abs(maxResolution - currentResolution);
    var down = Math.abs(maxResolution - resolution);
    var adjustedDuration = duration + Math.sqrt(up + down) * 100;

    view.animate({
      center: center,
      duration: adjustedDuration
    });
    view.animate({
      resolution: maxResolution,
      duration: adjustedDuration * up / (up + down)
    }, {
      resolution: resolution,
      duration: adjustedDuration * down / (up + down)
    });
  }
}