代码之家  ›  专栏  ›  技术社区  ›  marclar

如何在GoogleMapsv3中创建编号的地图标记?

  •  56
  • marclar  · 技术社区  · 15 年前

    我正在画一张上面有多个标记的地图。

    这些标记使用自定义图标,但我还想在顶部添加数字。我已经看到了如何使用旧版本的API来实现这一点。我怎样才能在v3中做到这一点?

    *注意-“title”属性在鼠标悬停在标记上时会创建一个工具提示,但我希望在自定义图像上分层,即使您不悬停在它上面。

    以下是Marker类的文档,这些属性似乎都没有帮助: http://code.google.com/apis/maps/documentation/v3/reference.html#MarkerOptions

    16 回复  |  直到 6 年前
        1
  •  62
  •   Erik Philips Gabriel Costa    12 年前

    不幸的是,这并不容易。您可以基于OverlayView类创建自己的自定义标记( an example )把你自己的HTML放进去,包括一个计数器。这将给您留下一个非常基本的标记,您不能轻松地拖动或添加阴影,但它是非常可定制的。

    或者,你可以 add a label to the default marker . 这将是不太可定制,但应该工作。它还保留了标准标记所做的所有有用的事情。

    你可以在谷歌的文章中阅读更多关于套印格式的内容。 Fun with MVC Objects .

    编辑:如果不想创建javascript类,可以使用 Google's Chart API . 例如:

    编号标记:

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

    文本标记:

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

    这是一个快速而简单的路径,但是它不太可定制,并且需要客户端为每个标记下载一个新的图像。

        2
  •  47
  •   jakob    11 年前

    我在v3中是这样做的:

    我首先加载google maps api并在回调方法中 initialize() 我载入 带label.js的marker 我发现的 here :

    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> 
    

    然后我用 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
                    });
                }
    

    自从我添加 地图标记 类到标记,我可以在我的CSS中添加一些CSS规则:

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

    结果是:

    MarkerWithIconAndLabel

        3
  •  27
  •   Alex    13 年前

    我没有足够的声誉对答案发表评论,但我想指出谷歌图表API已经被弃用。

    来自 API homepage :

    谷歌图表工具的信息图表部分已经正式 截至2012年4月20日已弃用。

        4
  •  21
  •   Halvor Holsten Strand mtorres    11 年前

    您可能希望从此网站提供的源文件下载一组编号的图标:

    然后您应该能够执行以下操作:

    <!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>
    

    以上示例的屏幕截图:

    Google Numbered Marker Icons

    请注意,您可以在标记后面轻松添加阴影。您可以在 Google Maps API Reference: Complex Markers 有关此的详细信息。

        5
  •  14
  •   John    9 年前

    现在已将其添加到映射文档中,不需要第三方代码。

    您可以组合这两个示例:

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

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

    要获得这样的代码:

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

    请注意,如果标记超过35个,此方法将不起作用,因为标签只显示第一个字符(使用a-z和0-9表示35)。请投这个票 Google Maps Issue 要求解除这一限制。

        6
  •  10
  •   Estevão Lucas    9 年前

    我使用类似于@zuzel的解决方案来完成这项工作。

    而不是使用默认解决方案( http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=7|FF0000|000000 ,您可以使用javascript创建这些图像,而不需要任何服务器端代码。

    google google.maps.marker接受base64作为其icon属性。通过这个,我们可以从SVG创建一个有效的base64。

    enter image description here

    您可以在这个窗口中看到生成与此图像相同的代码: 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>

    在这个演示中,我使用d3.js创建了SVG,然后将SVG转换为Canvas,这样我就可以根据需要调整图像的大小,然后从Canvas的ToDataURL方法获取base64。

    所有的演示都是基于我的同事 @蒂亚戈·马塔 代码。为他致敬。

        7
  •  9
  •   ZuzEL    9 年前

    这个怎么样?(2015年)

    1)获取自定义标记图像。

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

    2)创建 canvas 在里面 RAM 然后在上面画这个图像

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

    3)写上面的任何东西

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

    4)从canvas获取原始数据,并将其提供给google api而不是url

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

    enter image description here

    完整代码:

    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)
        };
    });
    
        8
  •  5
  •   ummdorian    9 年前

    谷歌地图3版内置了对标记标签的支持。不再需要生成自己的图像或实现第三方类。 Marker Labels

        9
  •  3
  •   user1032402    12 年前

    如果您有一些编程技巧,那么在服务器端生成标记图标是非常可行的。除了PHP之外,您还需要服务器上的gd库。几年来,我一直工作得很好,但要使图标图像同步,确实很难。

    我通过AJAX发送几个参数来定义空白图标、文本和颜色以及BGCULL。这是我的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']] ); 
    

    它通过如下方式调用客户端: var image_file=“”/our_icons/gen_icon.php?blank=“+escape(icons[color])+”&text=“+iconstr;

        10
  •  2
  •   Tim Cooper    12 年前

    我的两分钱展示了如何使用 Google Charts API 解决这个问题。

        11
  •  0
  •   Community CDub    8 年前

    基于 @dave1010 回答但更新了 https 链接。

    编号标记:

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

    文本标记:

    https://chart.googleapis.com/chart?chst=d_map_spin&chld=1|0|FF0000|12|_|Marker
    
        12
  •  0
  •   bCliks    10 年前

    您可以在google-maps-utility-library-v3中使用marker with label选项。 enter image description here

    只是参考 https://code.google.com/p/google-maps-utility-library-v3/wiki/Libraries

        13
  •  0
  •   agelbess    9 年前

    我发现了最好的方法。 使用 Snap.svg 要创建SVG,然后使用函数todataurl(),该函数创建要作为图标包含的图形数据。 注意,我使用slidingmarker类作为标记,它使我可以很好地移动标记。 使用snap.svg,您可以创建任何类型的图形,您的地图将看起来非常棒。

    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()
    });
    
        14
  •  0
  •   Community CDub    8 年前

    最简单的解决方案-使用SVG

    工作地点:工作地点 IE9 , IE10 、FF、Chrome、Safari

    (如果您使用其他浏览器,请“运行代码段”并放置注释)

    除了google maps api之外,没有其他依赖项!

    enter image description here

    这是 相当地 只要你的图标在 SVG 格式。如果是这样的话 添加 适当的文本元素并更改其内容以适应JS的需要。

    在您的 .svg 代码(这是文本“部分”,稍后将使用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>
    

    例子: (部分复制自@estevolucas)

    重要提示: 使用正确的 <text> 标记属性。音符 text-anchor="middle" x="50%" y="28" 哪个中心的号码比较长(更多信息: How to place and center text in an SVG rectangle )

    使用 encodeURIComponent() (这可能确保与IE9和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>

    有关谷歌地图中内嵌SVG的更多信息: https://robert.katzki.de/posts/inline-svg-as-google-maps-marker

        15
  •  0
  •   Nado11    6 年前

    也许有些人还在寻找这个,但是发现谷歌动态图标被弃用了,其他地图图标库有点太难看了。

    使用URL添加一个包含任意数字的简单标记。在使用google my maps的google驱动器中,当使用设置为“数字序列”的地图层,然后在地图上添加标记/点时,它会创建带编号的图标。

    从源代码来看,谷歌有自己的方式通过一个网址来实现它:

    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
    

    Above URL

    enter image description here

    我没有广泛使用它,但是通过更改“highlight”参数中的十六进制颜色代码(颜色参数不会改变您可能认为的颜色),“text”值可以设置为任何字符串,并且您可以制作一个内有任何数字/值的圆形图标。我相信其他参数也可能有用。

    这个方法有一个警告,谁知道谷歌什么时候会把这个网址从世界上删除呢!

        16
  •  -1
  •   Concept211    10 年前

    以下是具有更新的“视觉刷新”样式的自定义图标,您可以通过简单的.vbs脚本快速生成这些图标。我还包括一个大型的预生成集,您可以立即使用多种颜色选项: https://github.com/Concept211/Google-Maps-Markers

    链接到GitHub托管的图像文件时使用以下格式:

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

    颜色
    红色、黑色、蓝色、绿色、灰色、橙色、紫色、白色、黄色

    性格
    A-Z,1-100,!、@、$、+、-、=、(%23=)、(%25=%)、(%26=&)、(空白=•)

    示例:

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

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

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