Javascript 谷歌地图v3-我能保证每次都能顺利平移吗?
我的地图在一个城市里有几百个标记。通常半径不超过20英里。 我已经阅读了文档,还没有找到一种方法来设置init在每个标记之间自动平移,不管距离有多远。 默认行为是平移(如果接近),跳转(如果远)。 我理解他们为什么会这样做,因为地图没有在选定的缩放级别加载整个世界,如果距离太远,它可能会出错。然而,我认为它可以处理20英里半径的最小投诉 如果有人有什么想法,我很乐意听听。Javascript 谷歌地图v3-我能保证每次都能顺利平移吗?,javascript,google-maps,google-maps-api-3,Javascript,Google Maps,Google Maps Api 3,我的地图在一个城市里有几百个标记。通常半径不超过20英里。 我已经阅读了文档,还没有找到一种方法来设置init在每个标记之间自动平移,不管距离有多远。 默认行为是平移(如果接近),跳转(如果远)。 我理解他们为什么会这样做,因为地图没有在选定的缩放级别加载整个世界,如果距离太远,它可能会出错。然而,我认为它可以处理20英里半径的最小投诉 如果有人有什么想法,我很乐意听听。 感谢平滑平移的阈值不取决于当前中心和新目标之间的距离。这取决于更改是否需要整页滚动(水平和垂直): 引述: panTo(la
感谢平滑平移的阈值不取决于当前中心和新目标之间的距离。这取决于更改是否需要整页滚动(水平和垂直): 引述: panTo(latLng:latLng) 将贴图的中心更改为给定的板条。如果更改小于贴图的宽度和高度,则过渡将平滑设置动画
因此,只要将视口缩小到20英里的高度和宽度,就应该保证在20英里以下的距离内进行平滑平移。正如Daniel所提到的,如果两点之间的距离太远,内置的panTo()函数将不适用于您。如果是这种情况,您可以自己手动设置动画:对于每个缩放级别,计算100像素所覆盖的距离。现在,当您必须平移到某个点时,您可以使用此信息来确定panTo()函数将设置动画还是跳跃。如果移动的距离太大以至于无法设置动画,则应手动执行动画-计算当前地图中心和目的地之间的一些中间航路点,然后按顺序平移到它们。请参见另一个,回答关于使用javascript的
setInterval
函数创建一个周期函数,该函数在地图上调用panBy
:
这可用于在每次调用panBy时将地图平移x像素,从而降低平移速度(因为您只告诉GMAP平移一小段距离)。这是一个平滑平移的解决方案,还允许在上一次平移已在进行时将其他单击请求排队:
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]);
}
}
}
var panPath=[];//当前平移操作将使用的点数组
var panQueue=[];//要采取的一系列后续潘托行动
var步长=50;//每个panTo动作将经历的步骤数
功能panTo(新拉特、新液化天然气){
如果(panPath.length>0){
//我们已经在平移…请排队等待下一步
push([newLat,newLng]);
}否则{
//让我们计算我们将使用的点
push(“LAZY SYNCRONIZED LOCK”);//在调用setTimeout之前,将长度设置为非零-“释放”该值
var curLat=map.getCenter().lat();
var curLng=map.getCenter().lng();
var dLat=(newLat-curLat)/STEPS;
var dLng=(newLng-curLng)/步数;
对于(变量i=0;i
我们开发了一种变通方法,可以在所有情况下平滑地设置panTo
动画
基本上,如果本机的panTo
无法顺利动画化,我们将缩小
,panTo
和放大
到目标位置
要使用下面的代码,请调用smoothlyAnimatePanTo
将map
实例作为第一个参数传递,将目标latLng
作为第二个参数传递
有一个jsfiddle来演示这个解决方案。只需编辑脚本
标记,即可将您自己的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(map, 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(map, 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(map, 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)
}
}
/**
*将lat/lng投影到像素的便捷功能
*摘自:https://developers.google.com/maps/documentation/javascript/examples/map-coordinates
**/
功能项目(latLng){
var TILE_SIZE=256
var siny=Math.sin(latLng.lat()*Math.PI/180)
//截断为0.9999实际上将纬度限制为89.189。这是
//大约三分之一的瓷砖超过了世界瓷砖的边缘。
siny=Math.min(Math.max(siny,-0.9999),0.9999)
返回新的google.maps.Point(
瓷砖尺寸*(0.5+latLng.lng()/360),
瓷砖大小*(0.5-数学对数((1+siny)/(1-siny))/(4*数学PI)))
}
/**
*将lat/lng投影到像素的便捷功能
*摘自:https://developers.google.com/maps/documentation/javascript/examples/map-coordinates
**/
功能getPixel(放大、缩放){
var scale=1@tato.rodrigo
我没有足够的声誉来发布答案,所以我在这里作为对Tato的回复发布,因为他的插件对我来说很好,这正是我所需要的,但有一个bug(我将其用作依赖项,因此map
变量通过函数传递)
您需要将map
传递到函数getoptimizezoomout(latLng,currentZoom){}
当您在该函数中使用map
变量时
如下所示:函数getoptimizezoomout(latLng,currentZoom,map){}
之后:map.setZoom(getOptimalZoomOut(destLatLng,initialZoom));
传入:map.setZoom(getOptimalZoomOut(destLatLng,initialZoom,map));
可能还有另一个错误。永远不会少,是吗