3

What I have:

I set the icon for a Google Maps v3 Marker with

var icon= {
    url: 'path/to/iconfile.svg',
    [...]
};

var marker = new google.maps.Marker({
    icon: icon
    [...]
});

And it displays fine.


What I want:

Is there a way I can get that svg file from marker, change some attributes, and set it back to the marker?

I know you can do marker.getIcon() to get the actual Icon object, but is there something similar to marker.getIcon().getElementByID("iconID").setAttribute("fill", #000000); (which doesn't work, obviously), where I can change the SVG file through javascript?

3 Answers3

9

There is also a solution without the need to use URL.createObjectURL() which might be troublesome or not available in some cases.

You can use an alternative 'URL' with base64 encoded svg:

var svg = '<svg width="400" height="110"><rect width="300" height="100" /></svg>';
icon.url = 'data:image/svg+xml;charset=UTF-8;base64,' + btoa(svg);

JavaScript (Firefox) btoa() is used to get the base64 encoding from the SVG text. Your may also use http://dopiaza.org/tools/datauri/index.php to generate base data URLs.

Here is a full example:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
        <script src="http://maps.google.com/maps/api/js?sensor=false" type="text/javascript"></script>
    </head>
    <body>
        <div id="map" style="width: 500px; height: 400px;"></div>
        <script type="text/javascript">
            var map = new google.maps.Map(document.getElementById('map'), {
                zoom: 10,
                center: new google.maps.LatLng(-33.92, 151.25),
                mapTypeId: google.maps.MapTypeId.ROADMAP
            });

            var template = [
                '<?xml version="1.0"?>',
                    '<svg width="26px" height="26px" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">',
                        '<circle stroke="#222" fill="{{ color }}" cx="50" cy="50" r="35"/>',
                    '</svg>'
                ].join('\n');
            var svg = template.replace('{{ color }}', '#800');

            var docMarker = new google.maps.Marker({
                position: new google.maps.LatLng(-33.92, 151.25),
                map: map,
                title: 'Dynamic SVG Marker',
                icon: { url: 'data:image/svg+xml;charset=UTF-8;base64,' + btoa(svg) }
              });
        </script>
    </body>
</html>

Additional Information and an other solution using InfoBox can be found here.

Although this answer might be too late for you, it might help others looking for a solution to the same problem.

Tom
  • 1,470
  • 15
  • 13
  • Thanks! I didn't need to do the base64 encoding, but I did need to create the image with the `` tag and set that as the icon. Whenever I updated the color, I just replaced the `fill` attribute. Unfortunately, you can't do this with .svg _files_ only with code. – ThePersonWithoutC Mar 17 '16 at 19:12
  • 1
    If you would like to avoid base 64 encoding generally, there is also a version without it. See http://stackoverflow.com/questions/24413766/how-to-use-svg-markers-in-google-maps-api-v3/31338353?noredirect=1#answer-31338353 for details. – Tom Mar 21 '16 at 14:30
  • 1
    Dude, you rock! I need to create custom markers for google maps directions (since I want to keep my original markers too, on the map, and they would overlap with default direction icons....this would be the only solution for me to handle rotating the custom marker and adding dynamic text on the icon...awesome... – nenea Mar 03 '21 at 22:07
0

The HTML-elements representing the markers are not available via the API.

You must modify the property of the symbol(e.g. fillColor) and re-assign the modified symbol as icon-property of the marker:

var icon=marker.getIcon();
icon.fillColor='red';
marker.setIcon(icon); 

Demo(hover the symbol): http://jsfiddle.net/doktormolle/yxoy2zwe/

Dr.Molle
  • 116,463
  • 16
  • 195
  • 201
  • Thanks for the quick response. But `icon.fillColor='red';` only works if you explicitly define the paths for the icon, not if you use an .svg file. When I do `console.log(marker.getIcon());` I get `Object {url: "/images/icon_image.svg", size: U, origin: T, anchor: T, fillColor: "red"}`. It displays the icon, but the color is still the default black. – ThePersonWithoutC Sep 30 '14 at 14:30
0

I did this by creating a SVG template for marker and then rendering the template to a Blob which I pass as blob url to google maps. Then redo the same process when you want to change attributes of the SVG.

This is far from optimal solution but it's one way to make it work. Unfortunately this method will make the icon to flicker if you update it frequently.

Example code:

var template = [
    '<?xml version="1.0"?>',
    '<svg width="26px" height="26px" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">',
        '<circle stroke="#222" fill="{{ color }}" cx="50" cy="50" r="35"/>',
    '</svg>'
].join('\n');

var svg = template.replace('{{ color }}', '#888');
var blob = new Blob([svg], {type: 'image/svg+xml'});
var blobUrl = URL.createObjectURL(blob);

var image = {
    url: blobUrl,
    anchor: new google.maps.Point(13, 13)
};

var marker = new google.maps.Marker({
    position: map.getCenter(),
    map: map,  // Map object created earlier in the scope
    title: 'title',
    icon: image
});

// After finishing work with blob url, call:
// URL.revokeObjectURL(blobUrl);
Kimmo
  • 1,886
  • 1
  • 21
  • 28