Как вызвать fromLatLngToDivPixel в Google Maps API V3?

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


person Jader Dias    schedule 08.10.2009    source источник


Ответы (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!

person Tomas    schedule 23.11.2011
comment
Сначала у меня это отлично работает, но если я панорамирую карту, позиции пикселей не обновляются. Но если я затем изменю уровень zomm, он снова будет работать, как ожидалось (до следующего панорамирования). Я что-то упускаю? - person Roger Ertesvag; 06.03.2012
comment
Что касается предыдущего комментария, использование fromLatLngToContainerPixel вместо fromLatLngToDivPixel решило мою проблему с позициями пикселей, которые не обновлялись после панорамирования карты. - person Roger Ertesvag; 13.03.2012

Я думаю, что самый простой способ - игнорировать желание 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);
}
person Tiborg    schedule 19.08.2012
comment
Собственный пример Google: developers.google.com/maps/documentation/javascript/ examples / - person GoTo; 14.08.2014
comment
+1 за четкое выражение того, что делает Google в вашем первом абзаце ;-) Кроме того, он сделал эту услугу платной, чего мы совсем не ожидали. - person Tomas; 04.07.2019

Ответы здесь меня не удовлетворили. Поэтому я провел несколько экспериментов и нашел «простейшее» рабочее решение, близкое к ответу Ральфа, но, надеюсь, более понятное. (Я хочу, чтобы 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. И только после этого делайте то, что вам нужно.

person pixelfreak    schedule 10.08.2011
comment
это должен быть принятый ответ на вопрос. очень понятно - спасибо! - person Andres SK; 18.10.2011

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

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());
person Community    schedule 12.10.2009
comment
разве вы не смешиваете API v2 с v3? - person Jader Dias; 12.10.2009
comment
Я думаю, что это большая проблема с новым API. У него должен быть более простой способ сделать это - person Jader Dias; 13.10.2009

person    schedule
comment
Я попробовал этот код, и проекция переменной оказалась неопределенной. Есть идеи, почему? Спасибо! - person LaundroMat; 14.11.2010
comment
Примечание: (и это озадачило меня на добрые полчаса) - убедитесь, что вы создали наложение при создании карты, а НЕ когда вам нужны координаты (через fromLatLngToDivPixel). Если вы это сделаете, вы получите Uncaught TypeError: Cannot call method 'fromLatLngToDivPixel' of undefined. Похоже, что Google делает некоторые из этих вещей асинхронно. - person AlexeyMK; 12.08.2011
comment
@AlexeyMK Меня это тоже достало! пока я не нашел твой комментарий. - person shapeshifter; 05.12.2012