web-dev-qa-db-fra.com

Comment accéder à la division DIV du marqueur Google Maps API v3 et à sa position en pixels?

Au lieu de la fenêtre d'informations par défaut de l'API Google Maps, je vais utiliser un autre plug-in d'aide-mémoire jQuery au-dessus du marqueur. Il me faut donc obtenir la variable DIV du marqueur et sa position en pixels.

Mais n'a pas pu l'obtenir car il n'y a pas d'identifiant ni de classe pour certains marqueurs. Seul, je peux accéder à la carte canvas div à partir d'un objet marqueur et d'un objet non documenté pixelBounds.

  1. Comment puis-je accéder à la DIV de la marque?
  2. Où puis-je obtenir la position de pixel de DIV? Puis-je convertir la position de gauche à gauche en pixels?

== ajouté:

J'ai aussi essayé avec le code ci-dessous, mais cela ne change pas lorsque je fais défiler la carte. 

var marker = new google.maps.Marker({...});
google.maps.event.addListener(marker, 'click', function() {
    var px = this.getMap().getProjection().fromLatLngToPoint(this.getPosition());
    console.log("(" + px.x + "," + px.y + ")");
});
23
Ray Yun

Je ne comprends pas vraiment pourquoi voudriez-vous obtenir une division spécifique pour le marqueur? Si vous souhaitez afficher une info-bulle, tout ce dont vous avez besoin est la position en pixels de l'ancre des marqueurs (et des connaissances sur la taille du marqueur et le placement de l'ancre), et non un élément div. Vous pouvez toujours déclencher manuellement l'ouverture et la fermeture d'une info-bulle lorsqu'un événement se produit du côté de google.maps.

Pour obtenir la position de pixel de l'ancre d'un marqueur donné, vous pouvez utiliser ce code:

var scale = Math.pow(2, map.getZoom());
var nw = new google.maps.LatLng(
    map.getBounds().getNorthEast().lat(),
    map.getBounds().getSouthWest().lng()
);
var worldCoordinateNW = map.getProjection().fromLatLngToPoint(nw);
var worldCoordinate = map.getProjection().fromLatLngToPoint(marker.getPosition());
var pixelOffset = new google.maps.Point(
    Math.floor((worldCoordinate.x - worldCoordinateNW.x) * scale),
    Math.floor((worldCoordinate.y - worldCoordinateNW.y) * scale)
);

Dans pixelDistance, vous obtenez un décalage de l'ancre de marqueur spécifique compté à partir du coin supérieur gauche de la carte (et vous pouvez obtenir sa position à partir de map.getDiv() div). Pourquoi cela fonctionne-t-il (ou existe-t-il un meilleur moyen?), Vous pouvez lire dans la documentation de Google Maps overlays .

48
MBO
var overlay = new google.maps.OverlayView();
overlay.draw = function() {};
overlay.setMap(map);

var proj = overlay.getProjection();
var pos = marker.getPosition();
var p = proj.fromLatLngToContainerPixel(pos);

Vous pouvez maintenant accéder à vos coordonnées en pixels via p.x et p.y. 

SUIVANT AJOUTÉ POST COMMENTAIRE:

La projection de superposition a pour inconvénient de ne pas initialiser le canevas. L'auditeur suivant force la méthode à déclencher lorsque le chargement de la carte est terminé.

google.maps.event.addListener(map, 'idle', functionName());

En attendant, j'utilise le contrôle suivant pour éviter toute erreur avant que le tirage ne se déclenche.

if(overlay.getProjection()) {
  // code here
}
10
Flarex

Une chose à retenir lors de l'utilisation du code de MBO: Lorsque les mosaïques de la carte sont répétées, map.getBounds().getSouthWest() renvoie "-180" indépendamment de la position de la carte. Une solution de rechange que j'utilise dans ce cas consiste à calculer la distance en pixels par rapport au centre au lieu du coin supérieur gauche, car map.getCenter() semble renvoyer le point actuellement centré dans tous les cas. Par exemple. (en utilisant jQuery):

// Calculate marker position in pixels form upper left corner
var pixelCoordsCenter = map.getProjection().fromLatLngToPoint(map.getCenter());
pixelOffset = new google.maps.Point(
    Math.floor((pixelCoordsMarker.x - pixelCoordsCenter.x) * scale + $(container).width()/2),
    Math.floor((pixelCoordsMarker.y - pixelCoordsCenter.y) * scale + $(container).height()/2)
);
3
backflip

si vous êtes toujours à la recherche d'une réponse, consultez la page: http://code.google.com/p/google-maps-utility-library-v3/wiki/Libraries Il existe RichMarker dans Google Maps, ce qui vous permet d’ajouter des éléments DOM de votre choix sous forme de marqueurs déplaçables. ajoutez simplement class/id à gérer avec jQuery.

2
Eddie

Eh bien, si vous DEVEZ accéder au DIV, voici du code. Attention, cela ne fonctionnera qu'avec le marqueur standard (20x34px) et tous les marqueurs seront trouvés. Vous voudrez peut-être améliorer ce hack en fonction de vos besoins ...

IL FAUT SE MÉFIER! CECI IS UNE HACK

var a=document.getElementById('map_canvas');
var b=a.getElementsByTagName('img');
var i, j=b.length;
for (i=0; i<j; i++) {
  if(b[i].src.match('marker_Sprite.png')){
    if(b[i].style.width=='20px' && b[i].style.height=='34px') {
      c=b[i].parentElement;
      console.log(c.style.top+":"+c.style.left);
      // this is a marker's enclosing div

    }
  }
}
1
dda

La réponse de René ne vous donne que les "coordonnées du monde" (c'est-à-dire des coordonnées indépendantes du niveau de zoom et de la fenêtre d'affichage). La réponse de MBO semble juste, cependant, c'est donc celle que vous devriez accepter et voter (je ne peux pas, car je viens de m'inscrire), car la solution pourrait facilement être oubliée autrement.

Pour ce qui est de la version "plus facile", vous pouvez utiliser les méthodes de MapCanvasProjection à la place, mais cela signifie que vous devrez créer votre propre superposition. Voir ici pour un exemple. : P

1
Martin Lie

La fromLatLngToContainerPixel() de MapCanvasProjection correspond probablement à ce que recherche l'auteur. Cela vous donnera le décalage en pixels par rapport au conteneur de la carte. J'ai fait quelques expériences et trouvé la solution de travail "la plus simple". (J'aimerais que Google rend cette fonctionnalité plus accessible!)

Tout d’abord, vous déclarez une sous-classe de OverlayView quelque part comme ceci:

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

Puis ailleurs dans votre code où vous instanciez la carte, vous instanciez également cet OverlayView et définissez sa carte, comme suit:

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

Ensuite, chaque fois que vous devez utiliser fromLatLngToContainerPixel, procédez comme suit:

canvasProjectionOverlay.getProjection().fromLatLngToContainerPixel(myLatLng);

Notez que, comme l'objet MapCanvasProjection ne sera disponible qu'une fois que draw() est appelé, c'est-à-dire avant la idle de la carte, je suggère de créer un indicateur booléen "mapInitialized", définissez-le sur true lors du premier rappel idle de la carte. Et ensuite, faites ce que vous devez faire seulement après cela.

1
pixelfreak

Un fragment de style jQuery fonctionnel prêt à copier/coller:

étape 1 - initialisez votre carte et vos options

<html>
<head>
<script src="get-your-jQuery" type="text/javascript"></script>
<script src="get-your-maps.API" type="text/javascript"></script>
<script type="text/javascript">
<!--
$(document).ready(function(){
var bucharest = new google.maps.LatLng(44.43552, 26.10250);
var options = {
zoom: 14,
center: bucharest,
mapTypeId: google.maps.MapTypeId.ROADMAP 
}

Comme vous pouvez le voir, plus bas, la mappe de variable n'est pas précédée de VAR, car elle doit être globale car nous utilisons une autre fonction pour obtenir le fromLatLngToContainerPixel. Pour plus de détails, vérifiez fermetures .

map = new google.maps.map($("#map_canvas")[0], options);

var marker = new google.maps.Marker({
position: google.maps.LatLng(44.4407,26.0864),
map: map
});

new google.maps.event.addListener(marker, 'mouseover', function(){
          placeMarker( marker.getPosition(),'#tooltip');//param1: latlng, param2: container to place result
});

new google.maps.event.addListener(map, 'bounds_changed', function(){
        $("#tooltip").css({display:'none'}); //this is just so you can see that all goes well ;)
    });

 overlay = new google.maps.OverlayView();
 overlay.draw = function() {};
 overlay.setMap(map);

}); //here ends jQuery.ready

function placeMarker(location, ID){
var containerPixel = overlay.getProjection().fromLatLngToContainerPixel(location);
var divPixel       = overlay.getProjection().fromLatLngToDivPixel(location);
$(ID).css({top:containerPixel.y, left:containerPixel.x, 'dislay':'block'});
}
//--> 
</script>
</head>
<body>
<div id="tooltip" style="width:100px; height:100px; position:absolute; z-index:1; background:#fff">Here I am!</div>
<div id="map_canvas" style="width:300px; height:300px"></div>
</body>
</html>
0
amstegraf

J'ai trouvé qu'il était plus simple d'attribuer une icône personnalisée et d'utiliser l'attribut img src pour accéder à l'élément. Vous pouvez toujours utiliser l'icône Google Maps par défaut, il suffit de l'enregistrer localement.

$("#map img[src='my_marker.png']").getBoundingClientRect();
0
djangonaut

Dans de nombreuses circonstances, le calcul complexe utilisé pour calculer et modifier la position de la broche dans la réponse acceptée peut être approprié.

Pour mon utilisation particulière, je viens de créer un fichier PNG transparent avec une zone de travail bien plus grande que celle dont j'avais besoin pour l'icône. Ensuite, j'ai juste essayé de déplacer l'épingle dans l'arrière-plan transparent et d'appliquer la nouvelle image à la carte.

 adjusting the pin offset in photoshop

Voici la spécification pour l'ajout de l'image de broche personnalisée, avec des exemples: https://developers.google.com/maps/documentation/javascript/examples/icon-simple

Cette méthode sera certainement mise à l'échelle en tant que décalage en pixels au lieu d'un décalage réel différent, même lorsque vous effectuez un zoom avant.

0
squarecandy