olejniczag
olejniczag

Reputation: 394

SVG Icon is not visible in OpenLayers, while the other SVG is working correctly

I have an issue with displaying SVG image as icon in OL6. I've seen all similar issues here but it wasn't helpful. Here's the code of working icon image:

const workingIconFeature = new ol.Feature({
  geometry: new ol.geom.Point([0, 0])
});

const workingSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="30" height="91.19" style="fill: #fff"> <g> <g> <path d="M15,0A49,49,0,0,0,0,35L.2,70H29.8L30,35A49,49,0,0,0,15,0Z"/> <rect y="71.19" width="30" height="20"/> </g> </g> </svg>`;

const workingStyle = new ol.style.Style({
  image: new ol.style.Icon({
    opacity: 1,
    src: 'data:image/svg+xml;utf8,' + workingSvg,
    scale: 0.3
  })
});

workingIconFeature.setStyle(workingStyle);

Here's the icon that I can't display:

const notWorkingIconFeature = new ol.Feature({
  geometry: new ol.geom.Point([20, 20])
});

const notWorkingSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="45" height="110" viewBox="0 0 40 102">
          <defs>
              <style>
                  .a{fill:none;stroke:#fff;stroke-miterlimit:10;stroke-width:2px;}.a,.b{opacity:0.7;}.b{fill:#fff;}.c{fill:#031120;}
              </style>
          </defs>
          <line class="a" x1="20" y1="12" x2="20" y2="62" />
          <circle class="b" cx="20" cy="6" r="6" />
          <circle class="c" cx="20" cy="6" r="5" />
          <circle class="b" cx="20" cy="82" r="20" />
          <circle class="c" cx="20" cy="82" r="15" />
      </svg>`;

const notWorkingStyle = new ol.style.Style({
  image: new ol.style.Icon({
    opacity: 1,
    src: 'data:image/svg+xml;utf8,' + notWorkingSvg,
    scale: 0.3
  })
});

workingIconFeature.setStyle(notWorkingStyle);

http://jsfiddle.net/8afskcL2/2/

As you can see width and height attributes were added to not working but still with no effect. Maybe you know what can be an issue?

Upvotes: 1

Views: 2935

Answers (1)

geocodezip
geocodezip

Reputation: 161334

Your "working" style isn't working for me either (I see the default styled icon). You need to URL encode the svg. You can use escape.

working example with SVG icon

const workingStyle = new ol.style.Style({
  image: new ol.style.Icon({
    opacity: 1,
    src: 'data:image/svg+xml;utf8,' + escape(workingSvg),
    scale: 0.3
  })
});
const notWorkingStyle = new ol.style.Style({
  image: new ol.style.Icon({
    opacity: 1,
    src: 'data:image/svg+xml;utf8,' + escape(notWorkingSvg),
    scale: 0.3
  })
});

proof of concept fiddle

screenshot of map

code snippet:

const workingIconFeature = new ol.Feature({
  geometry: new ol.geom.Point([-1000, -1000])
});

const workingSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="30" height="91.19" style="fill: #0f0"> <g> <g> <path d="M15,0A49,49,0,0,0,0,35L.2,70H29.8L30,35A49,49,0,0,0,15,0Z"/> <rect y="71.19" width="30" height="20"/> </g> </g> </svg>`;

const workingStyle = new ol.style.Style({
  image: new ol.style.Icon({
    opacity: 1,
    src: 'data:image/svg+xml;utf8,' + escape(workingSvg),
    scale: 0.3
  })
});

workingIconFeature.setStyle(workingStyle);

const notWorkingIconFeature = new ol.Feature({
  geometry: new ol.geom.Point([1000, 1000])
});

const notWorkingSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="45" height="110" viewBox="0 0 40 102">
          <defs>
              <style>
                  .a{fill:none;stroke:#f00;stroke-miterlimit:10;stroke-width:2px;}.a,.b{opacity:0.7;}.b{fill:#f00;}.c{fill:#031120;}
              </style>
          </defs>
          <line class="a" x1="20" y1="12" x2="20" y2="62" />
          <circle class="b" cx="20" cy="6" r="6" />
          <circle class="c" cx="20" cy="6" r="5" />
          <circle class="b" cx="20" cy="82" r="20" />
          <circle class="c" cx="20" cy="82" r="15" />
      </svg>`;

const notWorkingStyle = new ol.style.Style({
  image: new ol.style.Icon({
    opacity: 1,
    src: 'data:image/svg+xml;utf8,' + escape(notWorkingSvg),
    scale: 0.3
  })
});

notWorkingIconFeature.setStyle(notWorkingStyle);

const vectorSource = new ol.source.Vector({
  features: [workingIconFeature, notWorkingIconFeature]
});

const vectorLayer = new ol.layer.Vector({
  source: vectorSource
});

const rasterLayer = new ol.layer.Tile({
  source: new ol.source.OSM()
});

const map = new ol.Map({
  layers: [rasterLayer, vectorLayer],
  target: document.getElementById('map'),
  view: new ol.View({
    center: [0, 0],
    zoom: 12
  })
});
html,
body {
  height: 100%;
  width: 100%;
  padding: 0px;
  margin: 0px;
}

.map {
  height: 100%;
  width: 100%;
}
<html lang="en">

<head>
  <link rel="stylesheet" href="https://openlayers.org/en/v6.4.2/css/ol.css" type="text/css">
  <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.2/build/ol.js"></script>
  <title>OpenLayers example</title>
</head>

<body>
  <div id="map" class="map"></div>
</body>

</html>

Upvotes: 2

Related Questions