我该如何在OpenLayers-3中使用SVG图像作为地图标记?

9

我正在尝试使用SVG图像在OpenLayers-3 (OL3)中创建地图“标记”(即地图标记)。

目前,我使用PNG图像作为引用ol.style.Icon源("src")属性的pindrops正常。然而,使用SVG图像则失败了。有没有其他方法可以以同样的方式使用SVG图像?也许是通过使用除ol.style.Icon之外的参考呢?在Open Layers中已经有很多内置的SVG,所以这应该是可能的,但我还没有找到在OL3中使其工作的方法。是否有其他在OL3中进行此操作的方法我应该考虑呢?

请注意: 我们已经尝试使用ol.Vector图层,但当用户缩放时,SVG图像的大小会增大/缩小,这是一个不充分的解决方案。


OL3(失败):

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];
    };
};

非常相似的功能,下面这个我在网上找到的例子几乎完美,如果不是因为该示例使用OpenLayers-2(OL2)功能调用了openlayers.js库(而不是OL3的ol.js库)。遗憾的是,交换这些javascript文件失败了。
OL2(可行但是使用了旧的OL库): http://dev.openlayers.org/sandbox/camptocamp/tipi/examples/vector-symbols.html
搜索在线解决方案似乎只会产生其他寻求解决方案的困惑人。
请帮忙处理,
FreeBeer

FYI,SVG是OpenLayers 2中支持的渲染器,但在OpenLayers 3中不再支持。ol3中支持的渲染器有:DOM、Canvas和WebGL。 - Alexandre Dubé
6个回答

10

根据 @ahocevar 的回答,您可以使用数据URI来处理SVG:

new ol.style.Style({
  image: new ol.style.Icon({
    anchor: [0, 0],
    src: 'data:image/svg+xml;utf8,<svg>/* SVG DATA */</svg>'
  })
});

1
很棒的解决方案,比base64更好,因为你甚至可以轻松地更改原始SVG内容(更改填充和描边颜色)。 要缩放SVG,可以直接通过图标样式的“scale”(0-1 = 0%-100%)属性来实现。 - fnicollet

5

将SVG转换为Base64编码。这个(链接)对我很有帮助。

复制Base64编码并将其用作javascript中的字符串。

例如:var svg = "转换后的Base64编码";

然后

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

你已经完成了,可能比SVG多几KB,但对我来说这非常完美。


5

我曾经遇到过同样的问题,但即使使用正确的MIME类型提供图像也没有帮助。

问题最终归结为SVG未正确定义宽度和高度。

我在<svg>标签中添加了widthheight属性,如下所示:

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

之后,我就可以像使用其他图片一样使用我的svg。


这对我很有用,只要我记得在宽度和高度值中添加“px”。花费一个小时进行调试是值得的... - Fredrik Boström

4

这是否意味着本地文件系统OL3地图无法使用SVG图标?我肯定无法使其正常工作。 - Tom Chadwin

1
我也遇到了显示图标图片的问题,ahocevar的答案帮助我解决了这个问题,但我还需要搜索php头文件来处理SVG格式。如果您或其他人正在使用php生成SVG,则必须使用header函数来识别内容类型。
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>';

0
借鉴SoonDead的答案,我不得不想出一种方法,在不触及源代码的情况下为SVG添加宽度和高度。使用Angular,我做了类似于以下的操作:
$http.get('path/to/image.svg').then(function (response) {
  // create element
  var svgEl = angular.element(response.data);

  // set width and height
  svgEl.attr('width', '50px');
  svgEl.attr('height', '50px');

  // base64 encode
  var base64Svg = btoa(unescape(encodeURIComponent(svgEl[0].outerHTML)));

  // create the style
  var style = new ol.style.Style({
    image: new ol.style.Icon({
      src: 'data:image/svg+xml;base64,'+base64Svg,
      imgSize: [50, 50],
      size: [50, 50],
    })
  });

 // apply the style
 feature.setStyle(style);
});

这段代码有点啰嗦,但似乎能胜任工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接