Can I use my converted image.svg as google map icon. I was converting my png image to svg and I want to use this like google map symbol that can be rotated. I already tried to use the google map symbol but I want to have an icon like car, man, etc... That's why I converted my some png files to svg, just like this example site what does he use for these http://www.goprotravelling.com/
-
1For those searching for this similar question: a partial IE 9+ compatible solution here: http://stackoverflow.com/a/30890373/634386 will place an SVG in the DOM instead of on the canvas so that you can manipulate with CSS3 after (if you're looking to rotate that element specifically on the fly). – Mike Kormendy Sep 22 '16 at 14:15
8 Answers
You can render your icon using the SVG Path notation.
See Google documentation for more information.
Here is a basic example:
var icon = {
path: "M-20,0a20,20 0 1,0 40,0a20,20 0 1,0 -40,0",
fillColor: '#FF0000',
fillOpacity: .6,
anchor: new google.maps.Point(0,0),
strokeWeight: 0,
scale: 1
}
var marker = new google.maps.Marker({
position: event.latLng,
map: map,
draggable: false,
icon: icon
});
Here is a working example on how to display and scale a marker SVG icon:
Edit:
Another example here with a complex icon:
Edit 2:
And here is how you can have a SVG file as an icon:
- 167,057
- 51
- 314
- 358
- 20,698
- 12
- 69
- 122
-
1
-
Do you have a SVG image of that car you want? Then just open it with a text editor and find the path in it! – MrUpsidown Jun 26 '14 at 12:48
-
-
can you please look at this http://www.goprotravelling.com/,is he uses an SVG file?the car,motorcyle and man walking? – jemz Jun 26 '14 at 12:52
-
It will be considered as a unicolor symbol. But you can change it. What can be tricky is to find the exact anchor point. Edit your link above. I don't see these symbols. – MrUpsidown Jun 26 '14 at 12:55
-
the complex icon is nice,but how did you do that to create like that?I converted my png to svg but it all turns to black – jemz Jun 26 '14 at 13:05
-
I meant to modify your link to goprotravelling.com it's wrong and I don't know where to look for these symbols. – MrUpsidown Jun 26 '14 at 13:10
-
3SVG is usually used for icons and other symbols. One color. It's just a path, like a letter in a font. The advantages is that you can easily scale it, rotate it and change its color, without losing quality. It's a vector shape. – MrUpsidown Jun 26 '14 at 13:13
-
-
We can't tell you what's wrong unless you show some code. JSFiddle! – MrUpsidown Jun 26 '14 at 14:37
-
I'd like to but my lat & lng are in my database,...the problem is that i have heading in corresponds with the coordinates,the car move to right it begun to upside down.that's the problem – jemz Jun 26 '14 at 15:25
-
Then at least provide a live URL to see your code. I have no idea why your SVG goes upside down. – MrUpsidown Jun 26 '14 at 15:56
-
,I have no live url i'm only work in my localhost,is it okay to have url in my screenshot?so that you can see.I will upload my screenshot in my dropbox – jemz Jun 26 '14 at 17:57
-
@MrUpsidown How can I take a complex svg image and break it down into path notation like you did in your complex example? Particularly when I have paths nested inside of paths? – E.E.33 Mar 31 '15 at 16:04
-
@E.E.33 There are tools for that. Inkscape, Illustrator can be helpful. Also, try to open your SVG file with a text editor (notepad, Sublime text, etc.) and you will see what you can find in it ;) – MrUpsidown Mar 31 '15 at 16:15
-
You can use an SVG file (with multiple elements, rather than just the single path definition they expose more fully) - you just need to ensure you have all the required properties - if you have size and scaledSize it works, and scale might also work (although I haven't tried that). scaledSize isn't required for non-SVG marker images and I ran into missing images and exceptions when trying to switch from a minimal PNG icon to SVG as a result. This also then supports data URIs, so if you generate SVG locally you can use a Base64 library to encode it and use that as your icon uri. – David Burton Jun 17 '15 at 11:37
-
You are right in that you can use a SVG file. The `scaledSize` property doesn't seem to be necessary though. – MrUpsidown Jun 17 '15 at 14:21
-
Answer updated with an example. You can remove the `scaledSize` and you will see it still works. – MrUpsidown Jun 17 '15 at 14:27
-
1That was one of the most useful things I read this year! Many thanks – Jonathan La'Fey Dec 08 '15 at 14:27
-
1. Some of your fiddles don't seem to be working. 2. What about SVG's consisting of more than one path? – Tigran Jan 15 '16 at 05:54
-
The last fiddle had a link to an icon that was no longer accessible. Updated. The second fiddle shows a multiple path SVG. See the [documentation](https://www.w3.org/TR/SVG/paths.html#PathDataGeneralInformation). – MrUpsidown Jan 15 '16 at 13:16
-
-
@MikeKormendy http://stackoverflow.com/questions/27494296/svg-not-showing-in-ie11 – MrUpsidown Sep 21 '16 at 06:47
-
2@MrUpsidown But of course SVG is working fine outside of maps - never had an issue there. It has to do with a glitch in Google's support for SVG in their canvas rendering - which can be turned off so that SVGs are inserted into the DOM instead. Then there's the issue with calculated sizes of the markers, which there are a couple properties in the implementation for map markers that can force the size.I've found a partial solution here: http://stackoverflow.com/a/30890373/634386 – Mike Kormendy Sep 22 '16 at 14:10
-
@MrUpsidown I wonder, would SVG path perform better than raster image? Let's say in load test scenario for thousands marker – stuckedoverflow Apr 19 '21 at 17:15
-
If you need a full svg not only a path and you want it to be modifiable on client side (e.g. change text, hide details, ...) you can use an alternative data 'URL' with included 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 jsfiddle:
<!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,' + encodeURIComponent(svg), scaledSize: new google.maps.Size(20, 20) },
optimized: false
});
var docMarker = new google.maps.Marker({
position: new google.maps.LatLng(-33.95, 151.25),
map: map,
title: 'Dynamic SVG Marker',
icon: { url: 'data:image/svg+xml;charset=UTF-8;base64,' + btoa(svg), scaledSize: new google.maps.Size(20, 20) },
optimized: false
});
</script>
</body>
</html>
Additional Information can be found here.
Avoid base64 encoding:
In order to avoid base64 encoding you can replace 'data:image/svg+xml;charset=UTF-8;base64,' + btoa(svg) with 'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent(svg)
This should work with modern browsers down to IE9.
The advantage is that encodeURIComponent is a default js function and available in all modern browsers. You might also get smaller links but you need to test this and consider to use ' instead of " in your svg.
Also see Optimizing SVGs in data URIs for additional info.
IE support: In order to support SVG Markers in IE one needs two small adaptions as described here: SVG Markers in IE. I updated the example code to support IE.
- 1,290
- 12
- 13
-
3Good info, but quick note that base64 encoding isn't actually necessary or desirable. You can use svg encoding directly in the data URI instead, like `data:image/svg+xml;utf8,`. More info: https://css-tricks.com/probably-dont-base64-svg/ – Josh from Qaribou Nov 25 '15 at 16:57
-
You are right it would be great if we could avoid the base64 encoding. How did you do it could you provide an example? If I just add the svg code to the URI it doesn't work with some chars like `#` did you use URL encoding? – Tom Nov 30 '15 at 18:01
-
I should mention it's utf8 encoded; svg is the format. The link provided has several examples. – Josh from Qaribou Dec 15 '15 at 13:40
-
1
-
Don't we all love IE ;) As usual it requires some additional work to make it work on all browsers. I adapted the example to support IE, hope this helps. – Tom Jul 03 '17 at 12:40
-
1The google maps team uses this same method for the default icons like street view, zoom in, zoom out, full screen, etc. – charlieb Jun 30 '21 at 20:41
I know this post is a bit old, but I have seen so much bad information on this at SO that I could scream. So I just gotta throw my two cents in with a whole different approach that I know works, as I use it reliably on many maps. Besides that, I believe the OP wanted the ability to rotate the arrow marker around the map point as well, which is different than rotating the icon around it's own x,y axis which will change where the arrow marker points to on the map.
First, remember we are playing with Google maps and SVG, so we must accomodate the way in which Google deploys it's implementation of SVG for markers (or actually symbols). Google sets its anchor for the SVG marker image at 0,0 which IS NOT the upper left corner of the SVG viewBox. In order to get around this, you must draw your SVG image a bit differently to give Google what it wants... yes the answer is in the way you actually create the SVG path in your SVG editor (Illustrator, Inkscape, etc...).
The first step, is to get rid of the viewBox. This can be done by setting the viewBox in your XML to 0... that's right, just one zero instead of the usual four arguments for the viewBox. This turns the view box off (and yes, this is semantically correct). You will probably notice the size of your image jump immeadiately when you do this, and that is because the svg no longer has a base (the viewBox) to scale the image. So we create that reference directly, by setting the width and height to the actual number of pixels you wish your image to be in the XML editor of your SVG editor.
By setting the width and height of the svg image in the XML editor you create a baseline for scaling of the image, and this size becomes a value of 1 for the marker scale properties by default. You can see the advantage this has for dynamic scaling of the marker.
Now that you have your image sized, move the image until the part of the image you wish to have as the anchor is over the 0,0 coordinates of the svg editor. Once you have done this copy the value of the d attribute of the svg path. You will notice about half of the numbers are negative, which is the result of aligning your anchor point for the 0,0 of the image instead of the viewBox.
Using this technique will then let you rotate the marker correctly, around the lat and lng point on the map. This is the only reliable way to bind the point on the svg marker you want to the lat and long of the marker location.
I tried to make a JSFiddle for this, but there is some bug in there implementation, one of the reasons I am not so fond of reinterpreted code. So instead, I have included a fully self-contained example below that you can try out, adapt, and use as a reference. This is the same code I tried at JSFiddle that failed, yet it sails through Firebug without a whimper.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="author" content="Drew G. Stimson, Sr. ( Epiphany )" />
<title>Create Draggable and Rotatable SVG Marker</title>
<script src="http://maps.googleapis.com/maps/api/js?sensor=false"> </script>
<style type="text/css">
#document_body {
margin:0;
border: 0;
padding: 10px;
font-family: Arial,sans-serif;
font-size: 14px;
font-weight: bold;
color: #f0f9f9;
text-align: center;
text-shadow: 1px 1px 1px #000;
background:#1f1f1f;
}
#map_canvas, #rotation_control {
margin: 1px;
border:1px solid #000;
background:#444;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
#map_canvas {
width: 100%;
height: 360px;
}
#rotation_control {
width: auto;
padding:5px;
}
#rotation_value {
margin: 1px;
border:1px solid #999;
width: 60px;
padding:2px;
font-weight: bold;
color: #00cc00;
text-align: center;
background:#111;
border-radius: 4px;
}
</style>
<script type="text/javascript">
var map, arrow_marker, arrow_options;
var map_center = {lat:41.0, lng:-103.0};
var arrow_icon = {
path: 'M -1.1500216e-4,0 C 0.281648,0 0.547084,-0.13447 0.718801,-0.36481 l 17.093151,-22.89064 c 0.125766,-0.16746 0.188044,-0.36854 0.188044,-0.56899 0,-0.19797 -0.06107,-0.39532 -0.182601,-0.56215 -0.245484,-0.33555 -0.678404,-0.46068 -1.057513,-0.30629 l -11.318243,4.60303 0,-26.97635 C 5.441639,-47.58228 5.035926,-48 4.534681,-48 l -9.06959,0 c -0.501246,0 -0.906959,0.41772 -0.906959,0.9338 l 0,26.97635 -11.317637,-4.60303 c -0.379109,-0.15439 -0.812031,-0.0286 -1.057515,0.30629 -0.245483,0.33492 -0.244275,0.79809 0.0055,1.13114 L -0.718973,-0.36481 C -0.547255,-0.13509 -0.281818,0 -5.7002158e-5,0 Z',
strokeColor: 'black',
strokeOpacity: 1,
strokeWeight: 1,
fillColor: '#fefe99',
fillOpacity: 1,
rotation: 0,
scale: 1.0
};
function init(){
map = new google.maps.Map(document.getElementById('map_canvas'), {
center: map_center,
zoom: 4,
mapTypeId: google.maps.MapTypeId.HYBRID
});
arrow_options = {
position: map_center,
icon: arrow_icon,
clickable: false,
draggable: true,
crossOnDrag: true,
visible: true,
animation: 0,
title: 'I am a Draggable-Rotatable Marker!'
};
arrow_marker = new google.maps.Marker(arrow_options);
arrow_marker.setMap(map);
}
function setRotation(){
var heading = parseInt(document.getElementById('rotation_value').value);
if (isNaN(heading)) heading = 0;
if (heading < 0) heading = 359;
if (heading > 359) heading = 0;
arrow_icon.rotation = heading;
arrow_marker.setOptions({icon:arrow_icon});
document.getElementById('rotation_value').value = heading;
}
</script>
</head>
<body id="document_body" onload="init();">
<div id="rotation_control">
<small>Enter heading to rotate marker </small>
Heading°<input id="rotation_value" type="number" size="3" value="0" onchange="setRotation();" />
<small> Drag marker to place marker</small>
</div>
<div id="map_canvas"></div>
</body>
</html>
This is exactly what Google does for it's own few symbols available in the SYMBOL class of the Maps API, so if that doesn't convince you... Anyway, I hope this will help you to correctly make and set up a SVG marker for your Google maps endevours.
- 1,768
- 1
- 18
- 14
-
2Nice answer, I've made a working fiddle of your code for people to see http://jsfiddle.net/v2pjfp7r/ – Rob Schmuecker Aug 26 '15 at 01:28
-
"<3" This is essential info that should be part of the google documentation. – user7653815 Nov 12 '19 at 11:38
-
This is the info I needed! If you're creating your SVG in Illustrator (after following the advice about viewBox above), make sure you use "Save As…" then save it as an SVG, "Export for Screens…" won't work. – Phil Mar 18 '21 at 16:25
-
This is the perfect answer - helped me solve an issue where the marker was drifting on zoom. Turned out to be caused by the anchor point not being set in the correct coordinate system. – 0xCC Oct 19 '21 at 16:40
Yes you can use an .svg file for the icon just like you can .png or another image file format. Just set the url of the icon to the directory where the .svg file is located. For example:
var icon = {
url: 'path/to/images/car.svg',
size: new google.maps.Size(sizeX, sizeY),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(sizeX/2, sizeY/2)
};
var marker = new google.maps.Marker({
position: event.latLng,
map: map,
draggable: false,
icon: icon
});
- 190
- 5
- 13
-
1The icon object you are showing is for a standard marker, not an SVG marker. An svg marker uses properties of the symbol class, which are then assigned as the icon property of the marker class. (see MrUpsidown icon object for a correct reference...) – Epiphany Mar 02 '15 at 17:51
-
2This will also break if the SVG has more than one 'd' path (usually associated with more than one layer in the svg image). – Epiphany Mar 02 '15 at 18:04
-
2Note that your svg file should explicitly set the dimensions of the icon like so: `width="33px" height="50px"` - see http://stackoverflow.com/a/21783089/165673 – Yarin Jun 13 '16 at 19:14
Things are going better, right now you can use SVG files.
marker = new google.maps.Marker({
position: {lat: 36.720426, lng: -4.412573},
map: map,
draggable: true,
icon: "img/tree.svg"
});
- 1,382
- 12
- 20
As mentioned by others in this thread, don't forget to explicitly set the width and height attributes in the svg like so:
<svg id="some_id" data-name="some_name" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 26 42"
width="26px" height="42px">
if you don't do that no js manipulation can help you as gmaps will not have a frame of reference and always use a standard size.
(i know it has been mentioned in some comments, but they are easy to miss. This information helped me in various cases)
- 8,843
- 3
- 40
- 39
OK! I done this soon in my web,I try two ways to create the custom google map marker, this run code use canvg.js is the best compatibility for browser.the Commented-Out Code is not support IE11 urrently.
var marker;
var CustomShapeCoords = [16, 1.14, 21, 2.1, 25, 4.2, 28, 7.4, 30, 11.3, 30.6, 15.74, 25.85, 26.49, 21.02, 31.89, 15.92, 43.86, 10.92, 31.89, 5.9, 26.26, 1.4, 15.74, 2.1, 11.3, 4, 7.4, 7.1, 4.2, 11, 2.1, 16, 1.14];
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 13,
center: {
lat: 59.325,
lng: 18.070
}
});
var markerOption = {
latitude: 59.327,
longitude: 18.067,
color: "#" + "000",
text: "ha"
};
marker = createMarker(markerOption);
marker.setMap(map);
marker.addListener('click', changeColorAndText);
};
function changeColorAndText() {
var iconTmpObj = createSvgIcon( "#c00", "ok" );
marker.setOptions( {
icon: iconTmpObj
} );
};
function createMarker(options) {
//IE MarkerShape has problem
var markerObj = new google.maps.Marker({
icon: createSvgIcon(options.color, options.text),
position: {
lat: parseFloat(options.latitude),
lng: parseFloat(options.longitude)
},
draggable: false,
visible: true,
zIndex: 10,
shape: {
coords: CustomShapeCoords,
type: 'poly'
}
});
return markerObj;
};
function createSvgIcon(color, text) {
var div = $("<div></div>");
var svg = $(
'<svg width="32px" height="43px" viewBox="0 0 32 43" xmlns="http://www.w3.org/2000/svg">' +
'<path style="fill:#FFFFFF;stroke:#020202;stroke-width:1;stroke-miterlimit:10;" d="M30.6,15.737c0-8.075-6.55-14.6-14.6-14.6c-8.075,0-14.601,6.55-14.601,14.6c0,4.149,1.726,7.875,4.5,10.524c1.8,1.801,4.175,4.301,5.025,5.625c1.75,2.726,5,11.976,5,11.976s3.325-9.25,5.1-11.976c0.825-1.274,3.05-3.6,4.825-5.399C28.774,23.813,30.6,20.012,30.6,15.737z"/>' +
'<circle style="fill:' + color + ';" cx="16" cy="16" r="11"/>' +
'<text x="16" y="20" text-anchor="middle" style="font-size:10px;fill:#FFFFFF;">' + text + '</text>' +
'</svg>'
);
div.append(svg);
var dd = $("<canvas height='50px' width='50px'></cancas>");
var svgHtml = div[0].innerHTML;
canvg(dd[0], svgHtml);
var imgSrc = dd[0].toDataURL("image/png");
//"scaledSize" and "optimized: false" together seems did the tricky ---IE11 && viewBox influent IE scaledSize
//var svg = '<svg width="32px" height="43px" viewBox="0 0 32 43" xmlns="http://www.w3.org/2000/svg">'
// + '<path style="fill:#FFFFFF;stroke:#020202;stroke-width:1;stroke-miterlimit:10;" d="M30.6,15.737c0-8.075-6.55-14.6-14.6-14.6c-8.075,0-14.601,6.55-14.601,14.6c0,4.149,1.726,7.875,4.5,10.524c1.8,1.801,4.175,4.301,5.025,5.625c1.75,2.726,5,11.976,5,11.976s3.325-9.25,5.1-11.976c0.825-1.274,3.05-3.6,4.825-5.399C28.774,23.813,30.6,20.012,30.6,15.737z"/>'
// + '<circle style="fill:' + color + ';" cx="16" cy="16" r="11"/>'
// + '<text x="16" y="20" text-anchor="middle" style="font-size:10px;fill:#FFFFFF;">' + text + '</text>'
// + '</svg>';
//var imgSrc = 'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent(svg);
var iconObj = {
size: new google.maps.Size(32, 43),
url: imgSrc,
scaledSize: new google.maps.Size(32, 43)
};
return iconObj;
};
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Your Custom Marker </title>
<style>
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="https://canvg.github.io/canvg/canvg.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap"></script>
</body>
</html>
- 77
- 6
You need to pass optimized: false.
E.g.
var img = { url: 'img/puff.svg', scaledSide: new google.maps.Size(5, 5) };
new google.maps.Marker({position: this.mapOptions.center, map: this.map, icon: img, optimized: false,});
Without passing optimized: false, my svg appeared as a static image.
- 150
- 1
- 6