Как позвонить изLatLngToDivPixel в Google Maps API V3?

Я знаю, что этот метод существует и документирован, но я не знаю, как получить объект MapCanvasProjection.

Ответ 1

Посмотрите 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!

Ответ 2

Я думаю, что самый простой способ - игнорировать стремление 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));
},

Теперь вы можете позвонить в любое время и в любом месте. Я особенно нуждался в нем для пользовательских контекстных меню, и он отлично работает.

EDIT: я также написал обратную функцию 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);
}

Ответ 3

Я не был удовлетворен ответами здесь. Поэтому я сделал несколько экспериментов и нашел "простейшее" рабочее решение, которое близко к ответу Ральфа, но, надеюсь, более понятно. (Я хочу, чтобы Google сделала эту функцию более доступной!)

Сначала вы объявляете подкласс 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", установить его на true на первой карте idle обратный вызов. И затем сделайте то, что вам нужно сделать только после этого.

Ответ 4

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();

Ответ 5

Чтобы получить MapCanvasProjection, вы можете получить класс из OverlayView и вызвать метод getProjection(), который возвращает MapCanvasProjection type

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 вы должны иметь возможность вызвать fromLatLngToDivPixel из своего экземпляра GMap2

var centerPoint = map.fromLatLngToDivPixel(map.getCenter());