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

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?

*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


Solution 1:

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.

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.

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

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.

Solution 2:

This how I do it in V3:

I start by loading the google maps api and within the callback method initialize() I load MarkerWithLabel.js that I found 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> 

I then create the markers with 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 mapIconLabel class to the marker I can add some css rules in my css:

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

And here is the result:

MarkerWithIconAndLabel