如何在 OpenLayers 中的两个远多边形之间创建飞行动画
How to create flying animations between two distant polygons in OpenLayers
使用 Openlayers (v6.1.1.) 我正在尝试在多个多边形之间创建简单的 FlyTo 动画。当它们之间的距离很小时,FlyTo 动画效果很好,但随着距离的增加,用户体验会下降。
在较远的距离上,我只能看到以低缩放比例快速平移地图。我试过 ahocevar answer from 但没有达到预期的效果。
按照说明,我将一个中心动画与两个缩放动画组合在一起,并同时启动它们。
示例:
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
});
当多边形在附近时,此 FlyTo 动画效果很好,但随着距离的增加,FlyTo 动画正在转变为在地图上快速平移。
我创建了用于测试目的的小应用程序。
当我们单击列表项时,地图将动画化并缩放到单击的字段。例如,当很棒的时候,另一个超级场就在附近,FlyTo 动画按预期工作,但是当我们从超级场点击史诗场(在最南端。然后地图只是快速平移到位置)。
所以,我的问题是这样的。是否有可能独立于多边形位置为多边形实现相同的 FlyTo 效果(传单中设置得很好 https://regionbound.com/leaflet-fly-demo)
这是 jsfiddle 示例:
https://jsfiddle.net/Svinjica/1kjfp4ds/
我认为您需要进一步改进缩放方式。例如,缩小到足以使起点和终点在最高海拔处都可见。您可以通过计算距离并除以地图宽度来做到这一点。对整体上下变化的持续时间做一些调整,但不要太多,按比例划分上涨和下跌的持续时间。如果当前分辨率已经大于计算出的峰值高度分辨率,则要减少初始持续时间,持续时间的 100% 应该向下,并且您还应该通过将地图拟合到 vectorSource 范围 [=11 来打开靠近要素所在位置的地图=]
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)
});
}
}
使用 Openlayers (v6.1.1.) 我正在尝试在多个多边形之间创建简单的 FlyTo 动画。当它们之间的距离很小时,FlyTo 动画效果很好,但随着距离的增加,用户体验会下降。
在较远的距离上,我只能看到以低缩放比例快速平移地图。我试过 ahocevar answer from
按照说明,我将一个中心动画与两个缩放动画组合在一起,并同时启动它们。 示例:
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
});
当多边形在附近时,此 FlyTo 动画效果很好,但随着距离的增加,FlyTo 动画正在转变为在地图上快速平移。
我创建了用于测试目的的小应用程序。 当我们单击列表项时,地图将动画化并缩放到单击的字段。例如,当很棒的时候,另一个超级场就在附近,FlyTo 动画按预期工作,但是当我们从超级场点击史诗场(在最南端。然后地图只是快速平移到位置)。
所以,我的问题是这样的。是否有可能独立于多边形位置为多边形实现相同的 FlyTo 效果(传单中设置得很好 https://regionbound.com/leaflet-fly-demo)
这是 jsfiddle 示例: https://jsfiddle.net/Svinjica/1kjfp4ds/
我认为您需要进一步改进缩放方式。例如,缩小到足以使起点和终点在最高海拔处都可见。您可以通过计算距离并除以地图宽度来做到这一点。对整体上下变化的持续时间做一些调整,但不要太多,按比例划分上涨和下跌的持续时间。如果当前分辨率已经大于计算出的峰值高度分辨率,则要减少初始持续时间,持续时间的 100% 应该向下,并且您还应该通过将地图拟合到 vectorSource 范围 [=11 来打开靠近要素所在位置的地图=]
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)
});
}
}