如何在 Google Maps API V3 中调用 fromLatLngToDivPixel?

IT技术 javascript google-maps google-maps-api-3 projection
2021-01-20 18:52:24

我知道该方法存在并记录在案,但我不知道如何获取 MapCanvasProjection 对象。

5个回答

http://qfox.nl/notes/116

var overlay = new google.maps.OverlayView();
overlay.draw = function() {};
overlay.setMap(map);
var point = overlay.getProjection().fromLatLngToDivPixel(latLng); 

确实丑 在 v2 中更容易 - google api v3 的另一个缺陷!

这最初对我来说非常有效,但是如果我平移地图,像素位置不会更新。但是,如果我然后更改 zomm 级别,它会再次按预期工作(直到下一个平移)。我错过了什么吗?
2021-03-25 18:52:24
关于之前的评论,使用 fromLatLngToContainerPixel 而不是 fromLatLngToDivPixel 解决了我的问题,即平移地图后像素位置未更新。
2021-03-29 18:52:24

我认为最简单的方法是忽略 Google 通过删除和隐藏有用的功能而不是添加新功能来使我们的生活变得更艰难的愿望,而只是编写自己的方法来做同样的事情。

这是某人在其他地方发布的函数的一个版本(我现在找不到),对我有用:

fromLatLngToPixel: function (position) {
  var scale = Math.pow(2, Map.getZoom());
  var proj = Map.getProjection();
  var bounds = Map.getBounds();

  var nw = proj.fromLatLngToPoint(
    new google.maps.LatLng(
      bounds.getNorthEast().lat(),
      bounds.getSouthWest().lng()
    ));
  var point = proj.fromLatLngToPoint(position);

  return new google.maps.Point(
    Math.floor((point.x - nw.x) * scale),
    Math.floor((point.y - nw.y) * scale));
},

现在,您可以随时随地调用它。我特别需要它用于自定义上下文菜单,它完美地完成了它的工作。

编辑:我还写了一个反向函数fromPixelToLatLng,它的作用正好相反。它只是基于第一个,并应用了一些数学:

fromPixelToLatLng: function (pixel) {
  var scale = Math.pow(2, Map.getZoom());
  var proj = Map.getProjection();
  var bounds = Map.getBounds();

  var nw = proj.fromLatLngToPoint(
    new google.maps.LatLng(
      bounds.getNorthEast().lat(),
      bounds.getSouthWest().lng()
    ));
  var point = new google.maps.Point();

  point.x = pixel.x / scale + nw.x;
  point.y = pixel.y / scale + nw.y;

  return proj.fromPointToLatLng(point);
}
2021-03-13 18:52:24
+1 在您的第一段中清楚地表达了 Google 正在做什么;-) 此外,他将其设为付费服务,这是我们根本没想到的。
2021-04-03 18:52:24

我对这里的答案并不满意。所以我做了一些实验,找到了“最简单”的工作解决方案,它接近 Ralph 的答案,但希望更容易理解。(我希望谷歌让这个功能更容易使用!)

首先,您OverlayView像这样声明某个地方的子类

function CanvasProjectionOverlay() {}
CanvasProjectionOverlay.prototype = new google.maps.OverlayView();
CanvasProjectionOverlay.prototype.constructor = CanvasProjectionOverlay;
CanvasProjectionOverlay.prototype.onAdd = function(){};
CanvasProjectionOverlay.prototype.draw = function(){};
CanvasProjectionOverlay.prototype.onRemove = function(){};

然后在你的代码中实例化地图的其他地方,你也实例化这个 OverlayView 并设置它的地图,像这样:

var map = new google.maps.Map(document.getElementById('google-map'), mapOptions);

// Add canvas projection overlay so we can use the LatLng to pixel converter
var canvasProjectionOverlay = new CanvasProjectionOverlay();
canvasProjectionOverlay.setMap(map);

然后,无论何时需要使用fromLatLngToContainerPixel,只需执行以下操作:

canvasProjectionOverlay.getProjection().fromLatLngToContainerPixel(myLatLng);

请注意,因为 MapCanvasProjection 对象仅在draw()调用一次后可用,即在地图之前的某个时间idle,我建议创建一个布尔值“mapInitialized”标志,在第一个地图idle回调时将其设置为 true 然后只做你需要做的事。

这应该是该问题的公认答案。非常清楚 - 谢谢!
2021-03-31 18:52:24
var map;
// Create your map
MyOverlay.prototype = new google.maps.OverlayView();
MyOverlay.prototype.onAdd = function() { }
MyOverlay.prototype.onRemove = function() { }
MyOverlay.prototype.draw = function() { }
function MyOverlay(map) { this.setMap(map); }
var overlay = new MyOverlay(map);
var projection = overlay.getProjection();
注意:(这让我难住了半个小时) - 确保在创建地图时创建叠加层,而不是在需要坐标时(通过 fromLatLngToDivPixel)。如果你这样做,你会得到 Uncaught TypeError: Cannot call method 'fromLatLngToDivPixel' of undefined。看起来谷歌异步地做一些这样的事情。
2021-03-22 18:52:24
@AlexeyMK 这也吸引了我!直到我找到你的评论。
2021-03-25 18:52:24
我试过这段代码,变量投影似乎是“未定义的”。知道为什么吗?谢谢!
2021-04-07 18:52:24

要获得 MapCanvasProjection,您可以从OverlayView派生一个类并调用返回MapCanvasProjection类型的 getProjection() 方法

必须实现 onAdd()、draw() 和 onRemove() 才能从 OverlayView 派生。

function MyOverlay(options) {
    this.setValues(options);

    var div = this.div_= document.createElement('div');

    div.className = "overlay";
};

// MyOverlay is derived from google.maps.OverlayView
MyOverlay.prototype = new google.maps.OverlayView;

MyOverlay.prototype.onAdd = function() {

    var pane = this.getPanes().overlayLayer;
    pane.appendChild(this.div_);

}

MyOverlay.prototype.onRemove = function() {
    this.div_.parentNode.removeChild(this.div_);
}

MyOverlay.prototype.draw = function() {
    var projection = this.getProjection();
    var position = projection.fromLatLngToDivPixel(this.getMap().getCenter());

    var div = this.div_;
    div.style.left = position.x + 'px';
    div.style.top = position.y + 'px';
    div.style.display = 'block';
};

那么当你创建你的地图时

var OverLayMap = new MyOverlay( { map: map } );

对于 V2, 您应该能够从 GMap2 实例调用 fromLatLngToDivPixel

var centerPoint = map.fromLatLngToDivPixel(map.getCenter());
我认为这是新 API 的一个大问题。它应该有一个更简单的方法来做到这一点
2021-03-13 18:52:24
你不是把 API v2 和 v3 混在一起了吗?
2021-03-28 18:52:24