web-dev-qa-db-fra.com

Comment créer des repères de carte numérotés dans Google Maps V3?

Je travaille sur une carte comportant plusieurs marqueurs.

Ces marqueurs utilisent une icône personnalisée, mais j'aimerais aussi ajouter des chiffres en haut. J'ai vu comment cela a été accompli avec d'anciennes versions de l'API. Comment puis-je faire cela en V3?

* Remarque - l'attribut "title" crée une info-bulle lorsque vous passez la souris sur le marqueur, mais je veux quelque chose qui sera superposé à l'image personnalisée même si vous ne la survolez pas.

Voici la documentation de la classe marker et aucun de ces attributs ne semble pouvoir vous aider: http://code.google.com/apis/maps/documentation/v3/reference.html#MarkerOptions

56
marclar

Malheureusement ce n'est pas très facile. Vous pouvez créer votre propre marqueur personnalisé basé sur la classe OverlayView ( un exemple ) et y insérer votre propre code HTML, y compris un compteur. Cela vous laissera avec un marqueur très basique, que vous ne pouvez pas faire glisser ou ajouter facilement des ombres, mais il est très personnalisable.

Vous pouvez également ajouter une étiquette au marqueur par défaut . Ce sera moins personnalisable mais devrait fonctionner. Il conserve également toutes les tâches utiles du marqueur standard.

Vous pouvez en savoir plus sur les incrustations dans l'article de Google Fun with MVC Objects .

Edit: si vous ne voulez pas créer de classe JavaScript, vous pouvez utiliser l'API graphique de Google . Par exemple:

Marqueur numéroté: 

http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=7|FF0000|000000

Marqueur de texte: 

http://chart.apis.google.com/chart?chst=d_map_spin&chld=1|0|FF0000|12|_|foo

Il s’agit d’un itinéraire simple et rapide, mais moins personnalisable et nécessitant le téléchargement d’une nouvelle image par le client pour chaque marqueur.

62
dave1010

Voici comment je le fais en V3:

Je commence par charger l'API Google Maps et dans la méthode de rappel initialize() je charge MarkerWithLabel.js que j'ai trouvé ici :

function initialize() {

            $.getScript("/js/site/marker/MarkerWithLabel.js#{applicationBean.version}", function(){

            var mapOptions = {
                zoom: 8,
                center: new google.maps.LatLng(currentLat, currentLng),
                mapTypeId: google.maps.MapTypeId.ROADMAP,
                streetViewControl: false,
                mapTypeControl: false
            };

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

            var bounds = new google.maps.LatLngBounds();

            for (var i = 0; i < mapData.length; i++) {
                createMarker(i+1, map, mapData[i]); <!-- MARKERS! -->
                extendBounds(bounds, mapData[i]);
            }
            map.fitBounds(bounds);
            var maximumZoomLevel = 16;
            var minimumZoomLevel = 11;
            var ourZoom = defaultZoomLevel; // default zoom level

            var blistener = google.maps.event.addListener((map), 'bounds_changed', function(event) {
                if (this.getZoom(map.getBounds) &gt; 16) {
                    this.setZoom(maximumZoomLevel);
                }
                google.maps.event.removeListener(blistener);
            });
            });
        }

        function loadScript() {
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = "https://maps.googleapis.com/maps/api/js?v=3.exp&amp;libraries=places&amp;sensor=false&amp;callback=initialize";
            document.body.appendChild(script);
        }

        window.onload = loadScript;

    </script> 

Je crée ensuite les marqueurs avec createMarker():

function createMarker(number, currentMap, currentMapData) {

   var marker = new MarkerWithLabel({
       position: new google.maps.LatLng(currentMapData[0], currentMapData[1]),
                 map: currentMap,
                 icon: '/img/sticker/empty.png',
                 shadow: '/img/sticker/bubble_shadow.png',
                 transparent: '/img/sticker/bubble_transparent.png',
                 draggable: false,
                 raiseOnDrag: false,
                 labelContent: ""+number,
                 labelAnchor: new google.maps.Point(3, 30),
                 labelClass: "mapIconLabel", // the CSS class for the label
                 labelInBackground: false
                });
            }

Depuis que j'ai ajouté la classe mapIconLabel au marqueur, je peux ajouter des règles CSS dans mon CSS:

.mapIconLabel {
    font-size: 15px;
    font-weight: bold;
    color: #FFFFFF;
    font-family: 'DINNextRoundedLTProMediumRegular';
}

Et voici le résultat:

MarkerWithIconAndLabel

47
jakob

Je n'ai pas assez de réputation pour commenter les réponses, mais je voulais noter que l'API Google Chart est obsolète.

Depuis la page d'accueil API :

La partie infographie de Google Chart Tools a été officiellement obsolète à compter du 20 avril 2012.

27
Alex

Vous pouvez télécharger un ensemble d’icônes numérotées à partir des sources fournies sur ce site:

Ensuite, vous devriez pouvoir faire ce qui suit:

<!DOCTYPE html>
<html> 
<head> 
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 
    <title>Google Maps Demo</title> 
    <script type="text/javascript"
            src="http://maps.google.com/maps/api/js?sensor=false"></script> 

    <script type="text/javascript"> 
    function initialize() {

      var myOptions = {
        zoom: 11,
        center: new google.maps.LatLng(-33.9, 151.2),
        mapTypeId: google.maps.MapTypeId.ROADMAP
      }

      var map = new google.maps.Map(document.getElementById("map"), myOptions);

      var locations = [
        ['Bondi Beach', -33.890542, 151.274856, 4],
        ['Coogee Beach', -33.923036, 151.259052, 5],
        ['Cronulla Beach', -34.028249, 151.157507, 3],
        ['Manly Beach', -33.80010128657071, 151.28747820854187, 2],
        ['Maroubra Beach', -33.950198, 151.259302, 1]
      ];

      for (var i = 0; i < locations.length; i++) {
          var image = new google.maps.MarkerImage('marker' + i + '.png',
                      new google.maps.Size(20, 34),
                      new google.maps.Point(0, 0),
                      new google.maps.Point(10, 34));

          var location = locations[i];
          var myLatLng = new google.maps.LatLng(location[1], location[2]);
          var marker = new google.maps.Marker({
              position: myLatLng,
              map: map,
              icon: image,
              title: location[0],
              zIndex: location[3]
          });
      }
    }
    </script> 
</head> 
<body style="margin:0px; padding:0px;" onload="initialize();"> 
    <div id="map" style="width:400px; height:500px;"></div> 
</body> 
</html>

Capture d'écran de l'exemple ci-dessus:

Google Numbered Marker Icons

Notez que vous pouvez facilement ajouter une ombre derrière les marqueurs. Vous voudrez peut-être consulter l’exemple figurant sous Référence de l'API Google Maps: Marqueurs complexes pour plus d'informations à ce sujet.

21
Daniel Vassallo

Cela a maintenant été ajouté à la documentation de mappage et ne nécessite aucun code tiers. 

Vous pouvez combiner ces deux exemples:

https://developers.google.com/maps/documentation/javascript/examples/marker-labels

https://developers.google.com/maps/documentation/javascript/examples/icon-simple

Pour obtenir un code comme celui-ci:

var labelIndex = 0;
var labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789';

function initialize() {
  var bangalore = { lat: 12.97, lng: 77.59 };
  var map = new google.maps.Map(document.getElementById('map-canvas'), {
    zoom: 12,
    center: bangalore
  });

  // This event listener calls addMarker() when the map is clicked.
  google.maps.event.addListener(map, 'click', function(event) {
    addMarker(event.latLng, map);
  });

  // Add a marker at the center of the map.
  addMarker(bangalore, map);
}

// Adds a marker to the map.
function addMarker(location, map) {
  // Add the marker at the clicked location, and add the next-available label
  // from the array of alphabetical characters.
  var marker = new google.maps.Marker({
    position: location,
    label: labels[labelIndex],
    map: map,
    icon: 'image.png'
  });
}

google.maps.event.addDomListener(window, 'load', initialize);

Notez que si vous avez plus de 35 marqueurs, cette méthode ne fonctionnera pas car l'étiquette affichera uniquement le premier caractère (en utilisant A à Z et 0 à 9, 35). Veuillez voter pour cela Problème Google Maps pour demander la levée de cette restriction.

14
John

Je l'ai fait en utilisant une solution similaire à @ZuzEL.

Au lieu d'utiliser la solution par défaut ( http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=7|FF0000|000000 ), vous pouvez créer ces images à votre guise, en utilisant JavaScript, sans code côté serveur.

Google google.maps.Marker accepte Base64 pour sa propriété icon. Avec cela, nous pouvons créer un Base64 valide à partir d'un SVG.

 enter image description here

Vous pouvez voir le code pour produire la même chose que cette image dans ce Plunker: http://plnkr.co/edit/jep5mVN3DsVRgtlz1GGQ?p=preview

var markers = [
  [1002, -14.2350040, -51.9252800],
  [2000, -34.028249, 151.157507],
  [123, 39.0119020, -98.4842460],
  [50, 48.8566140, 2.3522220],
  [22, 38.7755940, -9.1353670],
  [12, 12.0733335, 52.8234367],
];

function initializeMaps() {
  var myLatLng = {
    lat: -25.363,
    lng: 131.044
  };

  var map = new google.maps.Map(document.getElementById('map_canvas'), {
    zoom: 4,
    center: myLatLng
  });

  var bounds = new google.maps.LatLngBounds();

  markers.forEach(function(point) {
    generateIcon(point[0], function(src) {
      var pos = new google.maps.LatLng(point[1], point[2]);

      bounds.extend(pos);

      new google.maps.Marker({
        position: pos,
        map: map,
        icon: src
      });
    });
  });

  map.fitBounds(bounds);
}

var generateIconCache = {};

function generateIcon(number, callback) {
  if (generateIconCache[number] !== undefined) {
    callback(generateIconCache[number]);
  }

  var fontSize = 16,
    imageWidth = imageHeight = 35;

  if (number >= 1000) {
    fontSize = 10;
    imageWidth = imageHeight = 55;
  } else if (number < 1000 && number > 100) {
    fontSize = 14;
    imageWidth = imageHeight = 45;
  }

  var svg = d3.select(document.createElement('div')).append('svg')
    .attr('viewBox', '0 0 54.4 54.4')
    .append('g')

  var circles = svg.append('circle')
    .attr('cx', '27.2')
    .attr('cy', '27.2')
    .attr('r', '21.2')
    .style('fill', '#2063C6');

  var path = svg.append('path')
    .attr('d', 'M27.2,0C12.2,0,0,12.2,0,27.2s12.2,27.2,27.2,27.2s27.2-12.2,27.2-27.2S42.2,0,27.2,0z M6,27.2 C6,15.5,15.5,6,27.2,6s21.2,9.5,21.2,21.2c0,11.7-9.5,21.2-21.2,21.2S6,38.9,6,27.2z')
    .attr('fill', '#FFFFFF');

  var text = svg.append('text')
    .attr('dx', 27)
    .attr('dy', 32)
    .attr('text-anchor', 'middle')
    .attr('style', 'font-size:' + fontSize + 'px; fill: #FFFFFF; font-family: Arial, Verdana; font-weight: bold')
    .text(number);

  var svgNode = svg.node().parentNode.cloneNode(true),
    image = new Image();

  d3.select(svgNode).select('clippath').remove();

  var xmlSource = (new XMLSerializer()).serializeToString(svgNode);

  image.onload = (function(imageWidth, imageHeight) {
    var canvas = document.createElement('canvas'),
      context = canvas.getContext('2d'),
      dataURL;

    d3.select(canvas)
      .attr('width', imageWidth)
      .attr('height', imageHeight);

    context.drawImage(image, 0, 0, imageWidth, imageHeight);

    dataURL = canvas.toDataURL();
    generateIconCache[number] = dataURL;

    callback(dataURL);
  }).bind(this, imageWidth, imageHeight);

  image.src = 'data:image/svg+xml;base64,' + btoa(encodeURIComponent(xmlSource).replace(/%([0-9A-F]{2})/g, function(match, p1) {
    return String.fromCharCode('0x' + p1);
  }));
}

initializeMaps();
#map_canvas {
  width: 100%;
  height: 300px;
}
<!DOCTYPE html>
<html>

  <head>
    <link rel="stylesheet" href="style.css">
    
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
    
  </head>

  <body>
    <div id="map_canvas"></div>
  </body>
  
  <script src="script.js"></script>

</html>

Dans cette démo, je crée le fichier SVG à l'aide de D3.js, puis je le transforme en canevas, ce qui me permet de redimensionner l'image à ma guise et d'obtenir ensuite la méthode Base64 de canvas 'toDataURL.

Toute cette démo était basée sur le code de mon collègue @ thiago-mata. Bravo pour lui.

10
Estevão Lucas

Que dis-tu de ça? (année 2015)

1) Obtenez une image de marqueur personnalisé.

var imageObj = new Image();
    imageObj.src = "/markers/blank_pin.png"; 

2) Créer une canvas dans RAM et dessiner cette image dessus

imageObj.onload = function(){
    var canvas = document.createElement('canvas');
    var context = canvas.getContext("2d");
    context.drawImage(imageObj, 0, 0);
}

3) Écrivez n'importe quoi au dessus 

context.font = "40px Arial";
context.fillText("54", 17, 55);

4) Obtenir des données brutes de la toile et les transmettre à Google API au lieu d’URL

var image = {
    url: canvas.toDataURL(),
 };
 new google.maps.Marker({
    position: position,
    map: map,
    icon: image
 });

 enter image description here

Code complet: 

function addComplexMarker(map, position, label, callback){
    var canvas = document.createElement('canvas');
    var context = canvas.getContext("2d");
    var imageObj = new Image();
    imageObj.src = "/markers/blank_pin.png";
    imageObj.onload = function(){
        context.drawImage(imageObj, 0, 0);

        //Adjustable parameters
        context.font = "40px Arial";
        context.fillText(label, 17, 55);
        //End

        var image = {
            url: canvas.toDataURL(),
            size: new google.maps.Size(80, 104),
            Origin: new google.maps.Point(0,0),
            anchor: new google.maps.Point(40, 104)
        };
        // the clickable region of the icon.
        var shape = {
            coords: [1, 1, 1, 104, 80, 104, 80 , 1],
            type: 'poly'
        };
        var marker = new google.maps.Marker({
            position: position,
            map: map,
            labelAnchor: new google.maps.Point(3, 30),
            icon: image,
            shape: shape,
            zIndex: 9999
        });
        callback && callback(marker)
    };
});
9
ZuzEL

La version 3 de Google Maps comprend un support intégré pour les étiquettes de marqueur. Plus besoin de générer vos propres images ou d'implémenter des classes tierces. Etiquettes de marquage

5
ummdorian

Il est tout à fait possible de générer des icônes étiquetées côté serveur, si vous avez des compétences en programmation. Vous aurez besoin de la bibliothèque Gd sur le serveur, en plus de PHP. Cela fonctionne bien pour moi depuis plusieurs années maintenant, mais il est difficile de synchroniser les images d'icônes.

Je le fais via AJAX en envoyant les quelques paramètres permettant de définir l'icône vide, le texte et la couleur, ainsi que la couleur bg à appliquer. Voici mon PHP:

header("Content-type: image/png");
//$img_url = "./icons/gen_icon5.php?blank=7&text=BB";

function do_icon ($icon, $text, $color) {
$im = imagecreatefrompng($icon);
imageAlphaBlending($im, true);
imageSaveAlpha($im, true);

$len = strlen($text);
$p1 = ($len <= 2)? 1:2 ;
$p2 = ($len <= 2)? 3:2 ;
$px = (imagesx($im) - 7 * $len) / 2 + $p1;
$font = 'arial.ttf';
$contrast = ($color)? imagecolorallocate($im, 255, 255, 255): imagecolorallocate($im, 0, 0, 0); // white on dark?

imagestring($im, $p2, $px, 3, $text, $contrast);    // imagestring  ( $image, $font, $x, $y, $string, $color)

imagepng($im);
imagedestroy($im);
}
$icons =   array("black.png", "blue.png", "green.png", "red.png", "white.png", "yellow.png", "gray.png", "lt_blue.png", "orange.png");      // 1/9/09
$light =   array( TRUE,         TRUE,       FALSE,       FALSE,     FALSE,      FALSE,      FALSE,          FALSE,      FALSE);     // white text?

$the_icon = $icons[$_GET['blank']];             // 0 thru 8 (note: total 9)
$the_text = substr($_GET['text'], 0, 3);        // enforce 2-char limit
do_icon ($the_icon, $the_text,$light[$_GET['blank']] ); 

Il est appelé côté client via quelque chose comme ce qui suit: var image_file = "./our_icons/gen_icon.php?blank=" + escape (icons [color]) + "& text =" + iconStr;

3
user1032402

Mes deux cents montrant comment utiliser l'API Google Charts pour résoudre ce problème.

2
sebastian serrano

Vous pouvez utiliser l'option Marqueur avec étiquette dans google-maps-utility-library-v3 .enter image description here

Il suffit de consulter https://code.google.com/p/google-maps-utility-library-v3/wiki/Libraries

0
bCliks

Peut-être y en a-t-il qui cherchent encore cela, mais qui trouvent les icônes Google Dynamic obsolètes et d'autres bibliothèques d'icônes cartographiques un peu trop laides.

Pour ajouter un simple marqueur avec n'importe quel nombre à l'intérieur en utilisant une URL. Dans Google Drive, à l'aide de Google My Maps, il crée des icônes numérotées lors de l'utilisation d'un calque de carte défini sur "Séquence de numéros", puis de l'ajout de marqueurs/points sur la carte.

En regardant le code source, Google a sa propre façon de le faire via une URL:

https://mt.google.com/vt/icon/name=icons/onion/SHARED-mymaps-container-bg_4x.png,icons/onion/SHARED-mymaps-container_4x.png,icons/onion/1738-blank-sequence_4x.png&highlight=ff000000,0288D1,ff000000&scale=2.0&color=ffffffff&psize=15&text=56&font=fonts/Roboto-Medium.ttf

URL ci-dessus

 enter image description here

Je n'y ai pas beaucoup joué, mais en modifiant les codes de couleur hexadécimaux dans le paramètre 'highlight' (le paramètre color ne change pas la couleur, comme vous pouvez le penser), la valeur 'text' peut être définie sur n'importe quelle chaîne et vous permet une jolie icône ronde avec n'importe quel nombre/valeur à l'intérieur. Je suis sûr que les autres paramètres peuvent également être utiles.

Une mise en garde avec cette approche, qui sait quand Google supprimera cette URL du monde!

0
Nado11

Basé sur @ dave1010 answer mais avec des liens https mis à jour.

Marqueur numéroté:

https://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=7|FF0000|000000

Marqueur de texte:

https://chart.googleapis.com/chart?chst=d_map_spin&chld=1|0|FF0000|12|_|Marker
0
Pedro Lobito

J'ai découvert le meilleur moyen de le faire . Utilisez Snap.svg pour créer le svg, puis utilisez la fonction toDataURL () qui crée les données graphiques à inclure en tant qu'icône . Notez que j'utilise le Classe SlidingMarker pour le marqueur qui me donne un joli mouvement du marqueur . Avec Snap.svg, vous pouvez créer n’importe quel type de graphique et votre carte aura un look fantastique.

var s = Snap(100, 100);
s.text(50, 50, store.name);
// Use more graphics here.
var marker = new SlidingMarker({
  position: {lat: store.lat, lng: store.lng},
  map: $scope.map,
  label: store.name, // you do not need this
  title: store.name, // nor this
  duration: 2000,
  icon: s.toDataURL()
});
0
Αλέκος

LA SOLUTION LA PLUS FACILE - UTILISEZ SVG

Fonctionne dans: dans IE9, IE10, FF, Chrome, Safari

(si vous utilisez d'autres navigateurs, veuillez "exécuter un extrait de code" et insérer un commentaire)

Aucune dépendance externe à part l'API Google Maps!

 enter image description here

Ceci est assez facile à condition que votre icône soit au format .svg. Si tel est le cas, il suffit de ajouter un élément de texte approprié et de modifier son contenu pour l'adapter à vos besoins avec JS.

Ajoutez quelque chose comme ceci à votre code .svg (il s'agit du texte "section" qui sera ultérieurement modifié avec JS):

<text id="1" fill="#20539F" font-family="NunitoSans-ExtraBold, Nunito Sans" font-size="18" font-weight="600" letter-spacing=".104" text-anchor="middle" x="50%" y="28">1</text>

Exemple: (partiellement copié de @ EstevãoLucas)

Important: Utilisez les propriétés correctes de la balise <text>. Note text-anchor="middle" x="50%" y="28" quels numéros centraux sont plus longs (plus d'infos: Comment placer et centrer du texte dans un rectangle SVG )

Utilisez encodeURIComponent() (cela garantit probablement la compatibilité avec IE9 et 10)

// Most important part (use output as Google Maps icon)
function getMarkerIcon(number) {
  // inline your SVG image with number variable
  var svg = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="40" height="40" viewBox="0 0 40 40"> <defs> <rect id="path-1" width="40" height="40"/> <mask id="mask-2" width="40" height="40" x="0" y="0" fill="white"> <use xlink:href="#path-1"/> </mask> </defs> <g id="Page-1" fill="none" fill-rule="evenodd"> <g id="Phone-Portrait---320" transform="translate(-209 -51)"> <g id="Group" transform="translate(209 51)"> <use id="Rectangle" fill="#FFEB3B" stroke="#F44336" stroke-width="4" mask="url(#mask-2)" xlink:href="#path-1"/> <text id="1" fill="#20539F" font-family="NunitoSans-ExtraBold, Nunito Sans" font-size="18" font-weight="600" letter-spacing=".104" text-anchor="middle" x="50%" y="28">' + number + '</text> </g> </g> </g> </svg>';
  // use SVG without base64 see: https://css-tricks.com/probably-dont-base64-svg/
  return 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svg);
}

// Standard Maps API code
var markers = [
  [1, -14.2350040, -51.9252800],
  [2, -34.028249, 151.157507],
  [3, 39.0119020, -98.4842460],
  [5, 48.8566140, 2.3522220],
  [9, 38.7755940, -9.1353670],
  [12, 12.0733335, 52.8234367],
];

function initializeMaps() {
  var myLatLng = {
    lat: -25.363,
    lng: 131.044
  };

  var map = new google.maps.Map(document.getElementById('map_canvas'), {
    zoom: 4,
    center: myLatLng
  });

  var bounds = new google.maps.LatLngBounds();

  markers.forEach(function(point) {
      var pos = new google.maps.LatLng(point[1], point[2]);

      new google.maps.Marker({
        position: pos,
        map: map,
        icon: getMarkerIcon(point[0]),         
      });

      bounds.extend(pos);
  });

  map.fitBounds(bounds);
}

initializeMaps();
#map_canvas {
  width: 100%;
  height: 300px;
}
<!DOCTYPE html>
<html>

  <head>
    <link rel="stylesheet" href="style.css">
    
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>        
  </head>

  <body>
    <div id="map_canvas"></div>
  </body>
  
  <script src="script.js"></script>

</html>

Plus d'informations sur le SVG intégré dans Google Maps: https://robert.katzki.de/posts/inline-svg-as-google-maps-marker

0
jmarceli