我在这里和那里做了很多搜索。他们都没有给出满意的答案,我们只知道 Google Maps API v3 有一个限制,如果 panTo 目标超过当前中心的 1 个窗口高度/宽度,它将不会平滑。
不过,我想实现“稍微”更顺畅,而不仅仅是“跳跃”到目标。
这是我的解决方案(不完美,但我认为它比跳跃更好):
- 计算当前位置和目标位置之间的距离
- 分成几个部分,每个部分都比一个窗口少一点
- panTo每个部分实现“部分”平滑动画。
可以通过以下算法找出每个部分目标:
- 电流为 c(x,y)
- 目标是 t(x,y)
- 节数为 s
- 每个部分是 c(x) + (t(x) - c(x)) / s , c(y) + (t(y) - c(y)) / s
问题来了:如何计算节数?
它应该基于当前的缩放级别和窗口大小,对吧?
好的,我终于想出了一些这样的东西,它可以工作(但没有考虑缩放级别)
var distance = Math.sqrt(Math.abs(Math.pow(lastLocation.lat() - status.Lat, 2)) + Math.abs(Math.pow(lastLocation.lng() - status.Lng, 2)));
//console.info('last:' + lastLocation.lat() + ',' + lastLocation.lng());
//console.info('new:' + status.Lat + ',' + status.Lng);
//console.info('distance:' + distance);
var smoothFactor = 8.0 / 1440; //hard code for screen size without considering zoom as well...
var factor = $(window).width() * smoothFactor;
smoothPanSections = [];
var sectionCount = Math.ceil(distance / factor);
var sectionLat = (status.Lat - lastLocation.lat()) / sectionCount;
var sectionLng = (status.Lng - lastLocation.lng()) / sectionCount;
for (var i = 1; i <= sectionCount; i++) {
if (i < sectionCount) {
smoothPanSections.push({ Lat: lastLocation.lat() + sectionLat * i, Lng: lastLocation.lng() + sectionLng * i });
}
else
smoothPanSections.push({ Lat: status.Lat, Lng: status.Lng });
}
panStatus();
panStatus 是:
function panStatus() {
if (smoothPanSections.length > 0) {
var target = smoothPanSections.shift();
//still have more sections
if (smoothPanSections.length > 0) {
google.maps.event.addListenerOnce(map, 'idle', function () {
window.setTimeout(function () {
panStatus();
}, 100);
});
}
var location = new google.maps.LatLng(target.Lat, target.Lng);
map.panTo(location, zoomSize);
}
}