Javascript 如何在 Google Maps V3 中创建带编号的地图标记?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2436484/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 00:19:27  来源:igfitidea点击:

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

javascriptgoogle-mapsgoogle-maps-api-3

提问by marclar

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 accomplished using older versions of the API. How can I do this in V3?

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

*Note -- the "title" attribute creates a tooltip when you mouseover the marker, but I want something that will be layered on top of the custom image even when you're not hovering on top of it.

*注意——当您将鼠标悬停在标记上时,“标题”属性会创建一个工具提示,但我希望即使您没有将鼠标悬停在自定义图像之上,它也会分层放置在自定义图像之上。

Here's the documentation for the marker class, and none of these attributes seem to help: http://code.google.com/apis/maps/documentation/v3/reference.html#MarkerOptions

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

回答by dave1010

Unfortunately it's not very easy. You could create your own custom marker based on the OverlayView class (an example) and put your own HTML in it, including a counter. This will leave you with a very basic marker, that you can't drag around or add shadows easily, but it is very customisable.

不幸的是,这并不容易。您可以基于 OverlayView 类(示例)创建自己的自定义标记,并将您自己的 HTML 放入其中,包括一个计数器。这将为您留下一个非常基本的标记,您无法轻松拖动或添加阴影,但它非常可定制。

Alternatively, you could add a label to the default marker. This will be less customisable but should work. It also keeps all the useful things the standard marker does.

或者,您可以向默认标记添加标签。这将不太可定制,但应该可以工作。它还保留了标准标记所做的所有有用的事情。

You can read more about the overlays in Google's article Fun with MVC Objects.

您可以在 Google 的文章Fun with MVC Objects 中阅读有关叠加层的更多信息。

Edit: if you don't want to create a JavaScript class, you could use Google's Chart API. For example:

编辑:如果您不想创建 JavaScript 类,则可以使用Google's Chart API。例如:

Numbered marker:

编号标记:

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

Text marker:

文字标记:

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

This is the quick and easy route, but it's less customisable, and requires a new image to be downloaded by the client for each marker.

这是一种快速简便的方法,但它的可定制性较差,并且需要客户端为每个标记下载一个新图像。

回答by jakob

This how I do it in V3:

这是我在 V3 中的做法:

I start by loading the google maps api and within the callback method initialize()I load MarkerWithLabel.jsthat I found here:

我首先加载谷歌地图 api,然后在回调方法中initialize()加载我在这里找到的MarkerWithLabel.js

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> 

I then create the markers with createMarker():

然后我创建标记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
                });
            }

Since I added mapIconLabelclass to the marker I can add some css rules in my css:

由于我将mapIconLabel类添加到标记中,因此我可以在我的 css 中添加一些 css 规则:

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

And here is the result:

结果如下:

MarkerWithIconAndLabel

带图标和标签的标记

回答by Alex

I don't have enough reputation to comment on answers but wanted to note that the Google Chart API has been deprecated.

我没有足够的声誉来评论答案,但想指出 Google Chart API 已被弃用。

From the API homepage:

API 主页

The Infographics portion of Google Chart Tools has been officially deprecated as of April 20, 2012.

自 2012 年 4 月 20 日起,Google Chart Tools 的信息图表部分已正式弃用。

回答by Daniel Vassallo

You may want to download a set of numbered icons from the sources provided at this site:

您可能希望从本站点提供的资源中下载一组带编号的图标:

Then you should be able to do the following:

那么你应该能够做到以下几点:

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

Screenshot from the above example:

上面例子的截图:

Google Numbered Marker Icons

谷歌编号标记图标

Note that you can easily add a shadow behind the markers. You may want to check the example at the Google Maps API Reference: Complex Markersfor more info about this.

请注意,您可以轻松地在标记后面添加阴影。您可能需要查看Google Maps API Reference: Complex Markers 中的示例以获取更多信息。

回答by John

This has now been added to the Mapping documentation and requires no third party code.

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

You can combine these two samples:

您可以组合这两个示例:

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

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

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

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

To get code like this:

要获得这样的代码:

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

Note that if you have more than 35 markers, this method will not work as the label only shows the first character (using A-Z and 0-9 makes 35). Please vote for this Google Maps Issueto request that this restriction be lifted.

请注意,如果您有超过 35 个标记,此方法将不起作用,因为标签仅显示第一个字符(使用 AZ 和 0-9 为 35)。请为此Google 地图问题投票以请求取消此限制。

回答by Estev?o Lucas

I did this using a solution similar to @ZuzEL.

我使用类似于@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.

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

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

Google google.maps.Marker 接受 Base64 作为其图标属性。有了这个,我们可以从 SVG 创建一个有效的 Base64。

enter image description here

在此处输入图片说明

You can see the code to produce the same as this image in this Plunker: http://plnkr.co/edit/jep5mVN3DsVRgtlz1GGQ?p=preview

您可以在此 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.

在这个演示中,我使用 D3.js 创建了 SVG,然后将 SVG 转换为 Canvas,因此我可以根据需要调整图像大小,然后从 canvas 的 toDataURL 方法获取 Base64。

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

所有这些演示都基于我的同事@thiago-mata代码。为他点赞。

回答by ZuzEL

How about this? (year 2015)

这个怎么样?(2015年)

1) Get a custom marker image.

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

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

2) Create a canvasin RAMand draw this image on it

2) 创建一个canvasinRAM并在其上绘制此图像

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

3) Write anything above it

3)在它上面写任何东西

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

4) Get raw data from canvas and provide it to Google API instead of URL

4) 从画布中获取原始数据并将其提供给 Google API 而不是 URL

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

enter image description here

在此处输入图片说明

Full code:

完整代码:

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

回答by ummdorian

Google Maps version 3 has built-in support for marker labels. No need to generate your own images anymore or implement 3rd party classes. Marker Labels

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

回答by user1032402

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.

如果您有一定的编程技能,在服务器端生成带标签的图标是非常可行的。除了 PHP 之外,您还需要服务器上的 GD 库。多年来一直为我工作,但不可否认,要使图标图像同步很棘手。

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:

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

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

回答by sebastian serrano

My two cents showing how to use the Google Charts APIto solve this problem.

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