我的地图在一个城市内有几百个标记。通常不超过20英里半径。 我已经阅读了文档并且没有找到一种方法来设置init以在每个标记之间自动平移,无论距离如何。 默认行为是平移,如果关闭,跳转到远。 我明白为什么他们会这样做,因为地图不会在选定的缩放级别加载整个世界,如果距离太大,它可能会搞砸。但是,我认为它可以在最小的投诉下处理20英里半径。
如果有人有任何想法,我很乐意听到他们的意见。 感谢
答案 0 :(得分:21)
平滑平移的阈值不依赖于当前中心与新目标之间的距离。这取决于更改是否需要整页滚动(水平和垂直):
<强>哑剧(经纬度:经纬度)强>
将地图中心更改为给定的LatLng。如果更改小于地图的宽度和高度,则过渡将平滑地动画。
因此,只要缩小您的视口高度和宽度为20英里,就应保证在20英里以下的距离内进行平滑平移。
答案 1 :(得分:12)
这是一个平稳平移的解决方案,并允许其他点击请求在前一个平移已经进行时排队:
var panPath = []; // An array of points the current panning action will use
var panQueue = []; // An array of subsequent panTo actions to take
var STEPS = 50; // The number of steps that each panTo action will undergo
function panTo(newLat, newLng) {
if (panPath.length > 0) {
// We are already panning...queue this up for next move
panQueue.push([newLat, newLng]);
} else {
// Lets compute the points we'll use
panPath.push("LAZY SYNCRONIZED LOCK"); // make length non-zero - 'release' this before calling setTimeout
var curLat = map.getCenter().lat();
var curLng = map.getCenter().lng();
var dLat = (newLat - curLat)/STEPS;
var dLng = (newLng - curLng)/STEPS;
for (var i=0; i < STEPS; i++) {
panPath.push([curLat + dLat * i, curLng + dLng * i]);
}
panPath.push([newLat, newLng]);
panPath.shift(); // LAZY SYNCRONIZED LOCK
setTimeout(doPan, 20);
}
}
function doPan() {
var next = panPath.shift();
if (next != null) {
// Continue our current pan action
map.panTo( new google.maps.LatLng(next[0], next[1]));
setTimeout(doPan, 20 );
} else {
// We are finished with this pan - check if there are any queue'd up locations to pan to
var queued = panQueue.shift();
if (queued != null) {
panTo(queued[0], queued[1]);
}
}
}
答案 2 :(得分:4)
请参阅此其他有关使用javascript的setInterval
函数创建在地图上调用panBy
的定期函数的答案:Can Google Maps be set to a slow constant pan? Like a globe revolution?
这可用于在每次调用panBy时按x像素平移地图,允许你减慢panBy速率(因为你只是告诉gmaps panTo一小段距离)。
答案 3 :(得分:1)
正如丹尼尔所提到的,如果两点相距太远,内置的panTo()函数将不适合你。如果是这种情况,您可以手动为其自动设置动画:对于每个缩放级别,计算出100像素所覆盖的距离。现在,当你必须平移到一个点时,你可以使用这些信息来确定panTo()函数是否会动画或跳转。如果移动的距离太大而无法设置动画,则应手动执行动画 - 在当前地图中心和目的地之间计算一些中间航点,并按顺序平移它们。
答案 4 :(得分:1)
我们开发了一种变通方法,可以在所有情况下为panTo
设置流畅的动画。
基本上,如果原生panTo
的动画效果不佳,我们zoom out
,panTo
和zoom in
到目标位置。
要使用下面的代码,请调用smoothlyAnimatePanTo
,并将map
实例作为第一个参数,并将目标latLng
作为第二个参数。
有一个jsfiddle在操作here中演示此解决方案。只需编辑script
标签以放置您自己的Google Maps JavaScript API键即可。
任何评论和贡献都将受到欢迎。
/**
* Handy functions to project lat/lng to pixel
* Extracted from: https://developers.google.com/maps/documentation/javascript/examples/map-coordinates
**/
function project(latLng) {
var TILE_SIZE = 256
var siny = Math.sin(latLng.lat() * Math.PI / 180)
// Truncating to 0.9999 effectively limits latitude to 89.189. This is
// about a third of a tile past the edge of the world tile.
siny = Math.min(Math.max(siny, -0.9999), 0.9999)
return new google.maps.Point(
TILE_SIZE * (0.5 + latLng.lng() / 360),
TILE_SIZE * (0.5 - Math.log((1 + siny) / (1 - siny)) / (4 * Math.PI)))
}
/**
* Handy functions to project lat/lng to pixel
* Extracted from: https://developers.google.com/maps/documentation/javascript/examples/map-coordinates
**/
function getPixel(latLng, zoom) {
var scale = 1 << zoom
var worldCoordinate = project(latLng)
return new google.maps.Point(
Math.floor(worldCoordinate.x * scale),
Math.floor(worldCoordinate.y * scale))
}
/**
* Given a map, return the map dimension (width and height)
* in pixels.
**/
function getMapDimenInPixels(map) {
var zoom = map.getZoom()
var bounds = map.getBounds()
var southWestPixel = getPixel(bounds.getSouthWest(), zoom)
var northEastPixel = getPixel(bounds.getNorthEast(), zoom)
return {
width: Math.abs(southWestPixel.x - northEastPixel.x),
height: Math.abs(southWestPixel.y - northEastPixel.y)
}
}
/**
* Given a map and a destLatLng returns true if calling
* map.panTo(destLatLng) will be smoothly animated or false
* otherwise.
*
* optionalZoomLevel can be optionally be provided and if so
* returns true if map.panTo(destLatLng) would be smoothly animated
* at optionalZoomLevel.
**/
function willAnimatePanTo(map, destLatLng, optionalZoomLevel) {
var dimen = getMapDimenInPixels(map)
var mapCenter = map.getCenter()
optionalZoomLevel = !!optionalZoomLevel ? optionalZoomLevel : map.getZoom()
var destPixel = getPixel(destLatLng, optionalZoomLevel)
var mapPixel = getPixel(mapCenter, optionalZoomLevel)
var diffX = Math.abs(destPixel.x - mapPixel.x)
var diffY = Math.abs(destPixel.y - mapPixel.y)
return diffX < dimen.width && diffY < dimen.height
}
/**
* Returns the optimal zoom value when animating
* the zoom out.
*
* The maximum change will be currentZoom - 3.
* Changing the zoom with a difference greater than
* 3 levels will cause the map to "jump" and not
* smoothly animate.
*
* Unfortunately the magical number "3" was empirically
* determined as we could not find any official docs
* about it.
**/
function getOptimalZoomOut(latLng, currentZoom) {
if(willAnimatePanTo(map, latLng, currentZoom - 1)) {
return currentZoom - 1
} else if(willAnimatePanTo(map, latLng, currentZoom - 2)) {
return currentZoom - 2
} else {
return currentZoom - 3
}
}
/**
* Given a map and a destLatLng, smoothly animates the map center to
* destLatLng by zooming out until distance (in pixels) between map center
* and destLatLng are less than map width and height, then panTo to destLatLng
* and finally animate to restore the initial zoom.
*
* optionalAnimationEndCallback can be optionally be provided and if so
* it will be called when the animation ends
**/
function smoothlyAnimatePanToWorkarround(map, destLatLng, optionalAnimationEndCallback) {
var initialZoom = map.getZoom(), listener
function zoomIn() {
if(map.getZoom() < initialZoom) {
map.setZoom(Math.min(map.getZoom() + 3, initialZoom))
} else {
google.maps.event.removeListener(listener)
//here you should (re?)enable only the ui controls that make sense to your app
map.setOptions({draggable: true, zoomControl: true, scrollwheel: true, disableDoubleClickZoom: false})
if(!!optionalAnimationEndCallback) {
optionalAnimationEndCallback()
}
}
}
function zoomOut() {
if(willAnimatePanTo(map, destLatLng)) {
google.maps.event.removeListener(listener)
listener = google.maps.event.addListener(map, 'idle', zoomIn)
map.panTo(destLatLng)
} else {
map.setZoom(getOptimalZoomOut(destLatLng, map.getZoom()))
}
}
//here you should disable all the ui controls that your app uses
map.setOptions({draggable: false, zoomControl: false, scrollwheel: false, disableDoubleClickZoom: true})
map.setZoom(getOptimalZoomOut(destLatLng, initialZoom))
listener = google.maps.event.addListener(map, 'idle', zoomOut)
}
function smoothlyAnimatePanTo(map, destLatLng) {
if(willAnimatePanTo(map, destLatLng)) {
map.panTo(destLatLng)
} else {
smoothlyAnimatePanToWorkarround(map, destLatLng)
}
}
答案 5 :(得分:0)
@ tato.rodrigo
我没有足够的声誉来发布答案,所以在这里发布对Tato的回复,因为他的插件对我来说效果很好,正是我所需要的,但是有一个bug(我将其用作依赖项,因此map
变量通过函数传递)
您需要将map
传递给function getOptimalZoomOut(latLng, currentZoom) {}
在该函数中使用map
变量时。
像这样:function getOptimalZoomOut(latLng, currentZoom, map) {}
及更高版本:map.setZoom(getOptimalZoomOut(destLatLng, initialZoom));
传递给它:map.setZoom(getOptimalZoomOut(destLatLng, initialZoom, map));
,也许还有另一个流浪者。