How can I create numbered map markers in Google Maps V3?

后端 未结 16 909
予麋鹿
予麋鹿 2020-11-28 18:13

I\'m working on a map that has multiple markers on it.

These markers use a custom icon, but I\'d also like to add numbers on top. I\'ve seen how this has been accomp

相关标签:
16条回答
  • 2020-11-28 18:36

    I did this using a solution similar to @ZuzEL.

    Instead of use the default solution (http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=7|FF0000|000000), you can create these images as you wish, using JavaScript, without any server-side code.

    Google google.maps.Marker accepts Base64 for its icon property. With this we can create a valid Base64 from a SVG.

    You can see the code to produce the same as this image in this 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>

    In this demo I create the SVG using D3.js, then transformed SVG to Canvas, so I can resize the image as I want and after that I get Base64 from canvas' toDataURL method.

    All this demo was based on my fellow @thiago-mata code. Kudos for him.

    0 讨论(0)
  • 2020-11-28 18:36

    EASIEST SOLUTION - USE SVG

    Works in: in IE9, IE10, FF, Chrome, Safari

    (if you are using other browsers please "Run code snippet" and place a comment)

    No external dependencies besides Google Maps API!

    This is quite easy provided that you have your icon in .svg format. If that is the case just add appropriate text element and change its content to fit your needs with JS.

    Add something like this to your .svg code (this is text "section" which will be later changed with 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>
    

    Example: (partially copied from @EstevãoLucas)

    Important: Use correct <text> tag properties. Note text-anchor="middle" x="50%" y="28" which center longer numbers (more info: How to place and center text in an SVG rectangle)

    Use encodeURIComponent() (this probably ensures compatibility with IE9 and 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>

    More info about inline SVG in Google Maps: https://robert.katzki.de/posts/inline-svg-as-google-maps-marker

    0 讨论(0)
  • 2020-11-28 18:41

    I discovered the best way to do it. Use Snap.svg to create the svg and then use the function toDataURL() that creates the graphics data to include as icon. Note that I use the SlidingMarker class for the marker that gives me nice movement of the marker. With Snap.svg you can create any kind of graphics and your map will look fantastic.

    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 讨论(0)
  • 2020-11-28 18:41

    Here are custom icons with the updated "visual refresh" style that you can generate quickly via a simple .vbs script. I also included a large pre-generated set that you can use immediately with multiple color options: https://github.com/Concept211/Google-Maps-Markers

    Use the following format when linking to the GitHub-hosted image files:

    https://raw.githubusercontent.com/Concept211/Google-Maps-Markers/master/images/marker_[color][character].png
    

    color
    red, black, blue, green, grey, orange, purple, white, yellow

    character
    A-Z, 1-100, !, @, $, +, -, =, (%23 = #), (%25 = %), (%26 = &), (blank = •)

    Examples:

    https://raw.githubusercontent.com/Concept211/Google-Maps-Markers/master/images/marker_red1.png

    https://raw.githubusercontent.com/Concept211/Google-Maps-Markers/master/images/marker_blue2.png

    https://raw.githubusercontent.com/Concept211/Google-Maps-Markers/master/images/marker_green3.png

    0 讨论(0)
  • 2020-11-28 18:44

    You can use Marker With Label option in google-maps-utility-library-v3. enter image description here

    Just refer https://code.google.com/p/google-maps-utility-library-v3/wiki/Libraries

    0 讨论(0)
  • 2020-11-28 18:47

    It's quite feasible to generate labeled icons server-side, if you have some programming skills. You'll need the GD library at the server, in addition to PHP. Been working well for me for several years now, but admittedly tricky to get the icon images in synch.

    I do that via AJAX by sending the few parameters to define the blank icon and the text and color as well as bgcolor to be applied. Here's my 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']] ); 
    

    It's invoked client-side via something like the following: var image_file = "./our_icons/gen_icon.php?blank=" + escape(icons[color]) + "&text=" + iconStr;

    0 讨论(0)
提交回复
热议问题