I have an OpenLayers3 map on my local filesystem, and I want a point layer to use SVG icons. This seems to fail silently:

var style = new ol.style.Style({
    image: new ol.style.Icon({
        size: [95, 95],
        src: "styles/transport_aerodrome.svg"
    })
});

Is this because the SVG, since it is a local file, does not have content-type, but OL3 needs SVGs to have content-type: image/svg+xml? Or is there another reason this fails, and a way to fix it?

up vote 6 down vote accepted

I am not sure whether this is a file location problem or if it is a problem of the svg you use. As long as it is within the root folder of your app I can not see why is not working. Dont you have any firebug errors? try to use the following snip to check if it is working. I have tried it works fine.

var style = new ol.style.Style({
    image: new ol.style.Icon({
        src: 'http://www.williambuck.com/portals/0/Skins/WilliamBuck2014/images/location-icon.svg'
    })
});

Also consider removing the size you provide within your code snip. So call it like that

var style = new ol.style.Style({
image: new ol.style.Icon({
    src: "styles/transport_aerodrome.svg"
})
});

UPDATE if you can get the xml out of your svg file. try the following:

var svg = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="30px" height="30px" viewBox="0 0 30 30" enable-background="new 0 0 30 30" xml:space="preserve">'+    
'<path fill="#156BB1" d="M22.906,10.438c0,4.367-6.281,14.312-7.906,17.031c-1.719-2.75-7.906-12.665-7.906-17.031S10.634,2.531,15,2.531S22.906,6.071,22.906,10.438z"/>'+
'<circle fill="#FFFFFF" cx="15" cy="10.677" r="3.291"/></svg>';

var mysvg = new Image();
mysvg.src = 'data:image/svg+xml,' + escape(svg);

//and then declare your style with img and imgSize
var style = new ol.style.Style({
image: new ol.style.Icon({
    img: mysvg,
    imgSize:[30,30]
})
});
  • I've tried without the size, with no change. And your first example doesn't help me because the SVG is not a local file. Try to put together a minimal example and browse to it as a local file. That's what seems to be the problem for me. – Tom Chadwin Nov 28 '15 at 20:56
  • I have updated with one more option working locally for me. If you need it just for testing is fine but on production deployed apps you should have no problem getting it from url. – pavlos Nov 29 '15 at 0:10
  • I'd seen mention of writing out the inline XML. Not keen, but if it's the only way possible, I'll have to consider it. I'd still like authoritative confirmation of what causes this issue, though. – Tom Chadwin Nov 30 '15 at 12:22
  • Maybe this is not an ol problem. Did you try to use the svg file to dispaly for example as a background image of your html page. If it works then it is an ol3 problem .If not you know the way to find out the reason. On the other hand having a local file on the file system is not the proper way to run an app, so this case would not cause you problems on a deployed app – pavlos Nov 30 '15 at 12:35
  • I haven't tried taking OL3 out of the stack, no. I should explain why I need this to work, since you seem to be saying it should not be necessary. I develop the QGIS plugin qgis2web. It generates Leaflet and OL3 maps from QGIS projects. It has a preview window as part of its GUI. It therefore stores assets locally to populate the preview. These assets include marker SVGs. However, they fail to display in the preview, and that is the issue I am trying to solve. I believe this is a valid use case of locally-hosted OL3 with local SVG markers. – Tom Chadwin Nov 30 '15 at 12:57

It works if you just put in the svg in the src element ol.style.Icon, but if you scale it, the svg will become unsharp. In my case I use the same svg for multiple Zoom Levels and wanted a different size each zoom Level.

The way i got the scaling problem work is:

function getVectorImage(src, size) {
    var canvas = document.createElement('canvas');
    canvas.setAttribute("width", size);
    canvas.setAttribute("height", size);
    var ctx = canvas.getContext("2d");
    var img = new Image();
    img.onload = function() {
        ctx.drawImage(img, 0, 0, size, size);
    }
    img.src = src;
    return canvas;
}

//example: size = 25  and  imgSrc = "test.svg"
function getWfsStyle(size, imgSrc) {
    var img = getVectorImage(imgSrc, size);
    var style = new ol.style.Style({
        image : new ol.style.Icon({
            img : img,
            imgSize : [size, size]
        }),
        zIndex : 4
    });
    return style;
}

One thing that was missing for me was the width="Xpx" height="Ypx" attributes in the svg.

We're looking for long answers that provide some explanation and context. Don't just give a one-line answer; explain why your answer is right, ideally with citations. Answers that don't include explanations may be removed.

  • 2
    Pls explain how to set this attributes... – wittich Jun 21 '16 at 18:39
  • @wittich you can use anchor attributes for that and specify where the icon should appear and also it's size – Hicham Zouarhi Jun 28 '16 at 13:14
  • as legenwsait said, my svg was missing the width="Xpx" height="Ypx" attributes. when added it works finally – Victor V Mar 30 '17 at 17:47

It turns out that SVGs in IE11 need the value imgSize setting to the SVG's native dimensions. That seems to have been the problem. However, it seems not to work with size, so I now need to find out how I can resize them client-side.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.