Google maps Marker Label with multiple characters
Asked Answered
H

7

47

I am trying to add a 4 character label (eg 'A123') to a Google Maps marker which has a wide icon defined with a custom path.

var marker = new google.maps.Marker({
  position: latLon,
  label: { text: 'A123' },
  map: map,
  icon: {
    path: 'custom icon path',
    fillColor: '#000000',
    labelOrigin: new google.maps.Point(26.5, 20),
    anchor: new google.maps.Point(26.5, 43)
    scale: 1,
  }
});

The marker label API is restricted to a single character, so just shows a marker with 'A' in the example above. I have tried using chrome developer tools to hack the html which is created by gmaps and reinstate the longer label. It displays perfectly with no modifications to the css required, so I just need to find a way to reinstate the other label chars which Google maps has stripped.

I raised a Google Maps Issue to request that this restriction be lifted. Please consider voting for the Google issue by visiting link above and starring the issue to encourage Google to fix it - thanks!

But in the meantime, is there a workaround I can use to remove the one char restriction?

Is there a way I can create a custom extension of google.maps.Marker to show my longer label?

Hitandmiss answered 8/9, 2015 at 21:4 Comment(6)
Have you tried MarkerWithLabelNidanidaros
@Nidanidaros I looked at that, but I don't think MarkerWithLabel supports the icon path attribute for specifying the iconHitandmiss
Anyone else with this problem, please consider voting for this issue which would remove the need for MarkerWithLabel.Hitandmiss
I found a snippet over codepen and it works great. Check the answer below: https://mcmap.net/q/303381/-google-maps-marker-label-with-multiple-charactersMannie
its fixed now in google maps api itself code.google.com/p/gmaps-api-issues/issues/detail?id=8578#c28Pliers
Like @GauravShah mentioned, the API now allows multi-character labels. For usage examples of the new API, see my answer to a similar question.Hi
N
52

You can use MarkerWithLabel with SVG icons.

Update: The Google Maps Javascript API v3 now natively supports multiple characters in the MarkerLabel

proof of concept fiddle (you didn't provide your icon, so I made one up)

Note: there is an issue with labels on overlapping markers that is addressed by this fix, credit to robd who brought it up in the comments.

code snippet:

function initMap() {
  var latLng = new google.maps.LatLng(49.47805, -123.84716);
  var homeLatLng = new google.maps.LatLng(49.47805, -123.84716);

  var map = new google.maps.Map(document.getElementById('map_canvas'), {
    zoom: 12,
    center: latLng,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  });

  var marker = new MarkerWithLabel({
    position: homeLatLng,
    map: map,
    draggable: true,
    raiseOnDrag: true,
    labelContent: "ABCD",
    labelAnchor: new google.maps.Point(15, 65),
    labelClass: "labels", // the CSS class for the label
    labelInBackground: false,
    icon: pinSymbol('red')
  });

  var iw = new google.maps.InfoWindow({
    content: "Home For Sale"
  });
  google.maps.event.addListener(marker, "click", function(e) {
    iw.open(map, this);
  });
}

function pinSymbol(color) {
  return {
    path: 'M 0,0 C -2,-20 -10,-22 -10,-30 A 10,10 0 1,1 10,-30 C 10,-22 2,-20 0,0 z',
    fillColor: color,
    fillOpacity: 1,
    strokeColor: '#000',
    strokeWeight: 2,
    scale: 2
  };
}
google.maps.event.addDomListener(window, 'load', initMap);
html,
body,
#map_canvas {
  height: 500px;
  width: 500px;
  margin: 0px;
  padding: 0px
}
.labels {
  color: white;
  background-color: red;
  font-family: "Lucida Grande", "Arial", sans-serif;
  font-size: 10px;
  text-align: center;
  width: 30px;
  white-space: nowrap;
}
<script src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=geometry,places&ext=.js"></script>
<script src="https://cdn.rawgit.com/googlemaps/v3-utility-library/master/markerwithlabel/src/markerwithlabel.js"></script>
<div id="map_canvas" style="height: 400px; width: 100%;"></div>
Nidanidaros answered 8/9, 2015 at 22:51 Comment(7)
Yes - I've been trying to get that working inlining the MarkerWithLabel into the callback function called by the google maps init script. But I see Uncaught ReferenceError: MarkerWithLabel is not defined when I try to call new MarkerWithLabel(...)Hitandmiss
OK, I got this working another way, by wrapping the MarkerWithLabel code in a function function initMarkerWithLabel() and calling it from the google maps callback.Hitandmiss
Hmm, OK I did manage to get this working, but I see problems with overlapping pins: jsfiddle.net/LLd4drvx/1Hitandmiss
Applying the fix from this issue fixed the marker with overlapping labelsHitandmiss
That fix saved my ass! I was almost considering dropping the plugin altogether because of that issue.Guava
markerwithlabel googlecode.com link is no longer working, alternate link is rawgit.com/nmccready/…Inartistic
can somebody update "the fix" for overlapping labels? the link is brokenSingles
M
30

First of all, Thanks to code author!

I found the below link while googling and it is very simple and works best. Would never fail unless SVG is deprecated.

https://codepen.io/moistpaint/pen/ywFDe/

There is some js loading error in the code here but its perfectly working on the codepen.io link provided.

var mapOptions = {
    zoom: 16,
    center: new google.maps.LatLng(-37.808846, 144.963435)
  };
  map = new google.maps.Map(document.getElementById('map-canvas'),
      mapOptions);


var pinz = [
    {
        'location':{
            'lat' : -37.807817,
            'lon' : 144.958377
        },
        'lable' : 2
    },
    {
        'location':{
            'lat' : -37.807885,
            'lon' : 144.965415
        },
        'lable' : 42
    },
    {
        'location':{
            'lat' : -37.811377,
            'lon' : 144.956596
        },
        'lable' : 87
    },
    {
        'location':{
            'lat' : -37.811293,
            'lon' : 144.962883
        },
        'lable' : 145
    },
    {
        'location':{
            'lat' : -37.808089,
            'lon' : 144.962089
        },
        'lable' : 999
    },
];

 

for(var i = 0; i <= pinz.length; i++){
   var image = 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2238%22%20height%3D%2238%22%20viewBox%3D%220%200%2038%2038%22%3E%3Cpath%20fill%3D%22%23808080%22%20stroke%3D%22%23ccc%22%20stroke-width%3D%22.5%22%20d%3D%22M34.305%2016.234c0%208.83-15.148%2019.158-15.148%2019.158S3.507%2025.065%203.507%2016.1c0-8.505%206.894-14.304%2015.4-14.304%208.504%200%2015.398%205.933%2015.398%2014.438z%22%2F%3E%3Ctext%20transform%3D%22translate%2819%2018.5%29%22%20fill%3D%22%23fff%22%20style%3D%22font-family%3A%20Arial%2C%20sans-serif%3Bfont-weight%3Abold%3Btext-align%3Acenter%3B%22%20font-size%3D%2212%22%20text-anchor%3D%22middle%22%3E' + pinz[i].lable + '%3C%2Ftext%3E%3C%2Fsvg%3E';

  
   var myLatLng = new google.maps.LatLng(pinz[i].location.lat, pinz[i].location.lon);
   var marker = new google.maps.Marker({
      position: myLatLng,
      map: map,
      icon: image
  });
}
html, body, #map-canvas {
  height: 100%;
  margin: 0px;
  padding: 0px
}
<div id="map-canvas"></div>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDtc3qowwB96ObzSu2vvjEoM2pVhZRQNSA&signed_in=true&callback=initMap&libraries=drawing,places"></script>

You just need to uri-encode your SVG html and replace the one in the image variable after "data:image/svg+xml" in the for loop.

For uri encoding you can use uri-encoder-decoder

You can decode the existing svg code first to get a better understanding of what is written.

Mannie answered 2/6, 2016 at 3:40 Comment(4)
@Skoua Hey, whats brutal in this? ;) I think the svg code makes you say that. is it?Mannie
Yup that's the SVG but I understand it's the only way to modify the base64 image on the fly. I upvoted. :)Divebomb
Thanks. Actually the svg is uri encoded. Decode it using the given decoder and it will look more understandable. :)Mannie
I am using Angular 7 with ngmap and this is the only solution that worked. Kudos for a great workaroundDepurative
H
10

OK, here is one solution I have come up with which is pretty messed up.

I put the full label text into the div using the fontFamily label attribute. Then I use querySelectorAll to match the resulting style attributes to pull out the refs and rewrite the tags once the map has loaded:

var label = "A123";
var marker = new google.maps.Marker({
  position: latLon,
  label: {
    text: label,
    // Add in the custom label here
    fontFamily: 'Roboto, Arial, sans-serif, custom-label-' + label
  },
  map: map,
  icon: {
    path: 'custom icon path',
    fillColor: '#000000',
    labelOrigin: new google.maps.Point(26.5, 20),
    anchor: new google.maps.Point(26.5, 43), 
    scale: 1
  }
});

google.maps.event.addListener(map, 'idle', function() {
  var labels = document.querySelectorAll("[style*='custom-label']")
  for (var i = 0; i < labels.length; i++) {
    // Retrieve the custom labels and rewrite the tag content
    var matches = labels[i].getAttribute('style').match(/custom-label-(A\d\d\d)/);
    labels[i].innerHTML = matches[1];
  }
});

This seems pretty brittle. Are there any approaches which are less awful?

Hitandmiss answered 8/9, 2015 at 22:15 Comment(4)
Hacky? Yes, totally. Gets the job done? Most definitely. I think this is the best solution until the Google Maps API is updated.Elixir
I'll add for future devs: Remember to change the regex. For me it was just numbers, so [0-9]+ will do. Additionally there needs to be a check on matches being null. Also, I modified querySelectorAl("[style*='custom-label']")' to querySelectorAl("[style*='custom-label-']")' and got rid of the icon portion of the marker.Elixir
This was best solution for me. For me the "idle" event listener didn't always seem to pick up the dom elements added on zoom. (Seemed ok for panning, just wasn't reliable for zooming - perhaps because I am using in conjunction with MarkerClusterer). Instead I used setTimeout to check for existence of the smuggled font family every 100ms. This worked fine. Also useful to smuggle in a class for the label, if for example you want a background colour or similar.Sulphate
This is less awful because marker and label are separate objects: github.com/googlemaps/js-map-labelBadenpowell
S
4

As of API version 3.26.10, you can set the marker label with more than one characters. The restriction is lifted.

Try it, it works!

Moreover, using a MarkerLabel object instead of just a string, you can set a number of properties for the appearance, and if using a custom Icon you can set the labelOrigin property to reposition the label.

Source: https://code.google.com/p/gmaps-api-issues/issues/detail?id=8578#c30 (also, you can report any issues regarding this at the above linked thread)

Shondrashone answered 29/11, 2016 at 14:4 Comment(1)
As Internet is a live being, I believe we should priorize the edge solutions... Sad Stackexchange works priorizing only number of votes, here's the documentation section for MarkerLabel inside official Google Maps JS API: developers.google.com/maps/documentation/javascript/3.exp/…Sirdar
B
1

For anyone trying to

...in 2019, it's worth noting some of the code referenced here no longer exists (officially). Google discontinued support for the "MarkerWithLabel" project a long time ago. It was originally hosted on Google code here, now it's unofficially hosted on Github here.

But there is another project Google maintained until 2016, called "MapLabel"s. That approach is different (and arguably better). You create a separate map label object with the same origin as the marker instead of adding a mapLabel option to the marker itself. You can make a marker with label with multiple characters using js-marker-label.

Badenpowell answered 1/10, 2019 at 3:54 Comment(1)
...And... they are deprecated (still 2019 btw). It is super frustrating that any rabbit hole for answers here leads to deprecated code, and the official documentation still links to missing code etc. Really makes you wonder if relying on Google's products for business is feasible long term.Cognizable
P
1

You can change easy marker label css without use any extra plugin.

var marker = new google.maps.Marker({
        position: this.overlay_text,
        draggable: true,
        icon: '',
        label: {
          text: this.overlay_field_text,
          color: '#fff',
          fontSize: '20px',
          fontWeight: 'bold',
          fontFamily: 'custom-label'
        },
        map:map
      });
      marker.setMap(map);

$("[style*='custom-label']").css({'text-shadow': '2px 2px #000'})
Preraphaelite answered 26/12, 2019 at 6:33 Comment(0)
R
-1

A much simpler solution to this problem that allows letters, numbers and words as the label is the following code. More specifically, the line of code starting with "icon:". Any string or variable could be substituted for 'k'.

for (i = 0; i < locations.length; i++) 
      { 
      k = i + 1;
      marker = new google.maps.Marker({
      position: new google.maps.LatLng(locations[i][1], locations[i][2]),     
      map: map,
      icon: 'http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=' + k + '|FF0000|000000'
});

--- the locations array holds the lat and long and k is the row number for the address I was mapping. In other words if I had a 100 addresses to map my marker labels would be 1 to 100.

Rheostat answered 29/12, 2015 at 13:23 Comment(2)
Unfortunately, this doesn't address the main problem which is to allow a longer label with a custom icon which can accommodate more chars. For the case of 2 or more letters, the letters are well outside the marker pin and it doesn't look good at all: chart.apis.google.com/… chart.apis.google.com/… I wouldn't be able to use this on the website I'm developing because it looks broken.Hitandmiss
chart.apis.google.com does not allow a custom icon. At least it does not allow even a simple circle instead of pin.Unaccountable

© 2022 - 2024 — McMap. All rights reserved.