【问题标题】:How to convert from (x, y) screen coordinates to LatLng (Google Maps)如何从(x,y)屏幕坐标转换为 LatLng(谷歌地图)
【发布时间】:2014-08-09 14:02:40
【问题描述】:

我正在使用 Google Maps 和 Leap Motion 实现一个应用程序,而我现在想要的是一种将 (x, y) 屏幕坐标转换为 Google Maps LatLng 对象的方法。

我想实现这一点,例如,在用户使用 Leap Motion 指向的位置开始全景(街景)。

我知道 fromPointToLatLng 函数的存在,但我不知道使用它的正确方法是什么以及如何将我的 x 和 y 坐标转换为 lat lng 变量。

你能帮我解决这个问题吗?

【问题讨论】:

  • 我也想过模拟一个点击事件左右,但简单地用javascript触发鼠标事件不会触发正确的谷歌地图事件,因为他们定义了自己的事件......

标签: javascript google-maps google-maps-api-3


【解决方案1】:
function latLng2Point(latLng, map) {
  var topRight = map.getProjection().fromLatLngToPoint(map.getBounds().getNorthEast());
  var bottomLeft = map.getProjection().fromLatLngToPoint(map.getBounds().getSouthWest());
  var scale = Math.pow(2, map.getZoom());
  var worldPoint = map.getProjection().fromLatLngToPoint(latLng);
  return new google.maps.Point((worldPoint.x - bottomLeft.x) * scale, (worldPoint.y - topRight.y) * scale);
}

function point2LatLng(point, map) {
  var topRight = map.getProjection().fromLatLngToPoint(map.getBounds().getNorthEast());
  var bottomLeft = map.getProjection().fromLatLngToPoint(map.getBounds().getSouthWest());
  var scale = Math.pow(2, map.getZoom());
  var worldPoint = new google.maps.Point(point.x / scale + bottomLeft.x, point.y / scale + topRight.y);
  return map.getProjection().fromPointToLatLng(worldPoint);
}

【讨论】:

  • 是的,它有效!非常感谢,您为我节省了很多时间!
  • 我正在地图上构建叠加层,如何获得基于像素值的地图元素
  • 只是为了清楚,这给出了墨卡托投影点而不是 dom 像素值
【解决方案2】:

经过一些研究和一些失败后,我想出了一个解决方案。 根据link 的文档,我发现谷歌点的计算范围是 x:[0-256], y:[0-256] (瓷砖是 256x256 像素)和 (0,0)点是地图最左边的点(查看链接了解更多信息)。

但是,我的方法如下:

  • 拥有 x 和 y 坐标(它们是屏幕上的坐标 - 在地图上)我计算了 x 和 y 坐标被放置以响应包含地图的 div 的百分比(在我的情况下,孔窗)

  • 计算(可见)地图的 NortEast 和 SouthWest LatLng 边界

  • 在 google Points 中转换了边界

  • 借助 x 和 y 的边界和百分比,以谷歌点计算新的 lat 和 lng

  • 转换回纬度 lng

      // retrieve the lat lng for the far extremities of the (visible) map
      var latLngBounds = map.getBounds();
      var neBound = latLngBounds.getNorthEast();
      var swBound = latLngBounds.getSouthWest();
    
      // convert the bounds in pixels
      var neBoundInPx = map.getProjection().fromLatLngToPoint(neBound);
      var swBoundInPx = map.getProjection().fromLatLngToPoint(swBound);
    
      // compute the percent of x and y coordinates related to the div containing the map; in my case the screen
      var procX = x/window.innerWidth;
      var procY = y/window.innerHeight;
    
      // compute new coordinates in pixels for lat and lng;
      // for lng : subtract from the right edge of the container the left edge, 
      // multiply it by the percentage where the x coordinate was on the screen
      // related to the container in which the map is placed and add back the left boundary
      // you should now have the Lng coordinate in pixels
      // do the same for lat
      var newLngInPx = (neBoundInPx.x - swBoundInPx.x) * procX + swBoundInPx.x;
      var newLatInPx = (swBoundInPx.y - neBoundInPx.y) * procY + neBoundInPx.y;
    
      // convert from google point in lat lng and have fun :)
      var newLatLng = map.getProjection().fromPointToLatLng(new google.maps.Point(newLngInPx, newLatInPx));
    

希望这个解决方案也能帮助别人! :)

【讨论】:

    【解决方案3】:

    查看简单的解决方案(v3):

    map.getProjection().fromLatLngToPoint(marker.position);
    

    https://developers.google.com/maps/documentation/javascript/3.exp/reference#Projection

    【讨论】:

    • x 和 y 是否代表地图上的像素值,您可以使用它来放置其他一些 html 元素还是其他东西
    【解决方案4】:

    尽管原始发布者找到了解决方案,但仍基于现有 SO 问题代码添加替代解决方案。

    Based on this answer 我们可以找到 Google Maps API v3 进行转换的必要部分。它侧重于重新定位地图的中心。修改为从屏幕读取位置需要计算屏幕坐标与屏幕中心的差值。

    为了这个示例,我将函数重命名为 pixelOffsetToLatLng 并将其更改为返回位置(除此之外,与上面答案中的代码没有太大区别):

    function pixelOffsetToLatLng(offsetx,offsety) {
      var latlng = map.getCenter();
      var scale = Math.pow(2, map.getZoom());
      var nw = new google.maps.LatLng(
          map.getBounds().getNorthEast().lat(),
          map.getBounds().getSouthWest().lng()
      );
    
      var worldCoordinateCenter = map.getProjection().fromLatLngToPoint(latlng);
      var pixelOffset = new google.maps.Point((offsetx/scale) || 0,(offsety/scale) ||0);
    
      var worldCoordinateNewCenter = new google.maps.Point(
          worldCoordinateCenter.x - pixelOffset.x,
          worldCoordinateCenter.y + pixelOffset.y
      );
    
      var latLngPosition = map.getProjection().fromPointToLatLng(worldCoordinateNewCenter);
    
      return latLngPosition;
    }
    

    要调用它,您需要传递网页元素上的 X 和 Y 坐标:

      var x = mapElement.offsetWidth / 2 - screenPositionX;
      var y = screenPositionY - mapElement.offsetHeight / 2;
      pixelOffsetToLatLng(x,y);
    

    对于leap.js 方面,您只需将leap.js 坐标映射到网页,可以通过试验或使用类似这样工作的屏幕位置插件:

    var $handCursor = $('#hand-cursor'); // using jQuery here, not mandatory though
    
    Leap.loop(function(frame) {
      if (frame.hands.length > 0) {
        var hand = frame.hands[0];
        $handCursor.css({
          left: hand.screenPosition()[0] + 'px',
          top: hand.screenPosition()[1] + 'px'
        });
    
        if ((hand.grabStrength >= 0.6 && lastGrabStrength < 0.6)) {
          var x = mapElement.offsetWidth / 2 - hand.screenPosition()[0];
          var y = hand.screenPosition()[1] - mapElement.offsetHeight / 2;
          map.setCenter(pixelOffsetToLatLng(x, y));
        }
      }
    }).use('screenPosition', {
      scale: 0.5
    });
    

    这是一个关于如何在 2D 环境中使用 Leap.js 读取坐标的 Codepen 示例: http://codepen.io/raimo/pen/pKIko

    您可以使用鼠标或将手放在 Leap Motion 控制器上来使 Google 地图视图居中(请参阅红色“光标”以获得视觉提示)。

    【讨论】:

      【解决方案5】:

      显然,Google 已决定让生活更轻松。

      这是内置解决方案:

      Point point = googleMap.getProjection.toScreenLocation(latLng)

      LatLng latlng = googleMap.getProjection.fromScreenLocation(point)

      【讨论】:

        【解决方案6】:

        您需要知道地图元素中心的(x0,y0),地图中心的(lat0,lng0),以及每像素度数的比率r,对应于地图的缩放级别。那么

        lat(y) = lat0 + r(y-y0)
        lng(x) = lng0 + r(x-x0) 
        

        请注意,这是一个简化的线性化模型,适用于显示小区域的地图。

        【讨论】:

        • 度数/像素是什么意思?我该如何计算?我知道屏幕的大小、分辨率、缩放级别,据我所知,瓷砖是 256 像素,但我不知道它背后的数学原理,我不确定你想做什么以度数/像素表示。
        • LatLng 坐标以度为单位。 r 是每个像素的比率坐标。您必须为您的缩放级别找到它。它是一种简化的线性化模型,适用于显示小区域的地图。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-23
        • 1970-01-01
        相关资源
        最近更新 更多