Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use an SVG image as a map marker in OpenLayers-3?

I am trying to create map "pin-drops" (ie. map markers) in OpenLayers-3 (OL3) using SVG images.

Currently, I am using PNG images as the pindrops that reference the ol.style.Icon source (“src”) property attribute just fine. However, this fails using an SVG image. Is there some other way to use an SVG in the same manner? Maybe by using a reference besides ol.style.Icon even? There is already a lot of built-in SVG in Open Layers so this should be possible, but I haven't found a way to get this working in OL3. Is there some other way to do this in OL3 that I should consider?

Please note: we already tried using an ol.Vector layer, however when the user zooms in/out, the size of the SVG image grows/shrinks which is an inadequate workaround.


OL3 (fails):

var createMapMarkerImage = function() {
    return function(feature, resolution) {
        var iconStyle = new ol.style.Style({
            image: new ol.style.Icon( ({
                src: 'img/map_pindrop.svg'   // OL3 doesn’t like this, but accepts a .PNG just fine
            }))
        });
        return [iconStyle];
    };
};

Very similar functionality, is the below example I found online, is almost perfect if it weren’t for the fact that the example uses OpenLayers-2 (OL2) functionality which calls openlayers.js library (instead of OL3’s ol.js library). Sadly, swapping these javascript files out fails.


OL2 (works -but is the old OL library):

http://dev.openlayers.org/sandbox/camptocamp/tipi/examples/vector-symbols.html


Searching online for a solution to this seems to produce only other confused people searching for a solution.

Please help,

FreeBeer

like image 429
FreeBeer Avatar asked Mar 19 '15 18:03

FreeBeer


5 Answers

I had the same issue, but not even serving the image with the proper mime type helped.

It boiled down to the SVG not defining width and height properly.

I added the width and height attributes to the <svg> tag, like:

<svg width="100px" height="100px" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0.75 0 30 45" xml:space="preserve">

After that I was able to use my svg just like any other image.

like image 180
vinczemarton Avatar answered Oct 17 '22 19:10

vinczemarton


Convert the SVG to Base 64 . This (Link) helped me.

copied the base 64 and used it as a string in javascript .

Eg : var svg = "convertedBase64";

Then

var icon = new ol.style.Icon({
        src:'data:image/svg+xml;base64,'+svg ,
        other props
});

And you are done, may be a few Kbs more than SVG but this did work perfect for me .

like image 21
Hari Haran Avatar answered Oct 17 '22 20:10

Hari Haran


Based on @ahocevar answer, you can use data URIs for SVG:

new ol.style.Style({
  image: new ol.style.Icon({
    anchor: [0, 0],
    src: 'data:image/svg+xml;utf8,<svg>/* SVG DATA */</svg>'
  })
});
like image 40
André Moraes Avatar answered Oct 17 '22 20:10

André Moraes


SVG icons work fine as long as the content-type of your SVG image file is image/svg+xml. Also note that no external references are supported inside the SVG. OpenLayers 3 simply uses the drawImage function of the 2d context. You can find more details on the requirements of SVG content here: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Drawing_DOM_objects_into_a_canvas.

like image 33
ahocevar Avatar answered Oct 17 '22 19:10

ahocevar


I also had issues to show the icon image, ahocevar answer helped me to solve my problem but I had also to search for the php header, for SVG In case you are or others who see this answer are using php to generate the SVG you have to use header function to identify the content-type

header('Content-type: image/svg+xml'); /* this line will do the magic */
echo '<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg">
<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>
</svg>';
like image 26
talsibony Avatar answered Oct 17 '22 20:10

talsibony