Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/388.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 谷歌地图v3-我能保证每次都能顺利平移吗?_Javascript_Google Maps_Google Maps Api 3 - Fatal编程技术网

Javascript 谷歌地图v3-我能保证每次都能顺利平移吗?

Javascript 谷歌地图v3-我能保证每次都能顺利平移吗?,javascript,google-maps,google-maps-api-3,Javascript,Google Maps,Google Maps Api 3,我的地图在一个城市里有几百个标记。通常半径不超过20英里。 我已经阅读了文档,还没有找到一种方法来设置init在每个标记之间自动平移,不管距离有多远。 默认行为是平移(如果接近),跳转(如果远)。 我理解他们为什么会这样做,因为地图没有在选定的缩放级别加载整个世界,如果距离太远,它可能会出错。然而,我认为它可以处理20英里半径的最小投诉 如果有人有什么想法,我很乐意听听。 感谢平滑平移的阈值不取决于当前中心和新目标之间的距离。这取决于更改是否需要整页滚动(水平和垂直): 引述: panTo(la

我的地图在一个城市里有几百个标记。通常半径不超过20英里。 我已经阅读了文档,还没有找到一种方法来设置init在每个标记之间自动平移,不管距离有多远。 默认行为是平移(如果接近),跳转(如果远)。 我理解他们为什么会这样做,因为地图没有在选定的缩放级别加载整个世界,如果距离太远,它可能会出错。然而,我认为它可以处理20英里半径的最小投诉

如果有人有什么想法,我很乐意听听。
感谢

平滑平移的阈值不取决于当前中心和新目标之间的距离。这取决于更改是否需要整页滚动(水平和垂直):

引述:

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));
可能还有另一个错误。

永远不会少,是吗