SVG支持嵌入位图图片吗?

182

SVG图像是纯矢量图还是可以将位图图像合并到SVG图像中?对于应用于位图图像的变换(透视、映射等)又怎么样?

编辑:可以通过链接引用将图像包含在SVG中。请参见http://www.w3.org/TR/SVG/struct.html#ImageElement。我的问题实际上是,位图图像是否可以包含在SVG内,使得SVG图像是自包含的。否则,每当显示SVG图像时,就必须跟随链接并下载图像。显然,.svg文件只是xml文件。

7个回答

258

是的,您可以从image元素引用任何图像。而且,您可以使用数据 URI使SVG自包含。一个例子:

<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">

    ...
    <image
        width="100" height="100"
        xlink:href="data:image/png;base64,IMAGE_DATA"
        />
    ...
</svg>

svg元素的属性xmlns:xlink声明了xlink作为一个命名空间前缀,并指定了定义的位置。这样,SVG阅读器就可以知道xlink:href的含义

IMAGE_DATA是您将图像数据添加为base64编码文本的位置。支持SVG的矢量图形编辑器通常有一个选项用于保存嵌入图像。否则,有许多工具可用于对字节流进行base64编码和解码。

以下是来自SVG测试套件的完整示例


2
@Aleksandar 这是一个独立的问题,我相信你可以在这个网站上找到答案(将某些内容编码为base64不仅适用于svg)。 - Erik Dahlström
1
@Erik - 假设我在同一个 SVG 文件中重复使用了一千次相同的图像。我能否将 Base64 数据放置在一个位置,并让这些图像从那里引用该数据? - Rohit Vats
3
没问题,我从这里找到了答案- http://stackoverflow.com/questions/16685014/image-causes-pixelated-image。答案中提到了组合。 :) - Rohit Vats
3
不要忘记将命名空间xlink声明为:xmlns:xlink="http://www.w3.org/1999/xlink",某些浏览器/查看器可能在没有此命名空间的情况下无法显示您的图像。 - Marc_Alx
2
根据我的经验,Chrome浏览器即使在svg图像标签中没有指定widthheight属性,也会显示该图像。然而,Firefox和IE如果省略这些属性,则不会显示图像。因此,请确保您指定它们! - Stonecrusher
显示剩余3条评论

33

我在这里发布了一个fiddle,展示了嵌入在HTML页面内的SVG中的数据、远程和本地图像:

http://jsfiddle.net/MxHPq/

<!DOCTYPE html>
<html>
<head>
    <title>SVG embedded bitmaps in HTML</title>
    <style>

        body{
            background-color:#999;
            color:#666;
            padding:10px;
        }

        h1{
            font-weight:normal;
            font-size:24px;
            margin-top:20px;
            color:#000;
        }

        h2{
            font-weight:normal;
            font-size:20px;
            margin-top:20px;
        }

        p{
            color:#FFF;
            }

        svg{
            margin:20px;
            display:block;
            height:100px;
        }

    </style>
</head>

<body>
    <h1>SVG embedded bitmaps in HTML</h1>
    <p>The trick appears to be ensuring the image has the correct width and height atttributes</p>

    <h2>Example 1: Embedded data</h2>
    <svg id="example1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
        <image x="0" y="0" width="5" height="5" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="/>
    </svg>

    <h2>Example 2: Remote image</h2>
    <svg id="example2" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
        <image x="0" y="0" width="275" height="95" xlink:href="http://www.google.co.uk/images/srpr/logo3w.png" />
    </svg>

    <h2>Example 3: Local image</h2>
    <svg id="example3" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
        <image x="0" y="0" width="136" height="23" xlink:href="/img/logo.png" />
    </svg>


</body>
</html>

23

您可以使用数据URI来提供图像数据,例如:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">

<image width="20" height="20" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="/>

</svg>

这个图像将经历所有正常的 SVG 变换。

但是这种技术有缺点,例如图像将无法被浏览器缓存。


如果SVG需要数据URI,那么这显然不是什么缺点——我会编辑我的答案。 - GarethOwen
1
嵌入式图像(数据URI)将与它们所在的文档一起被缓存,例如请参见https://dev59.com/BW445IYBdhLWcg3wkLTU。 - Erik Dahlström
如果SVG文档发生更改,即使是相同的嵌入式位图也将重新加载。如果我们链接到HTTP URL,则可以将其与SVG文档分别缓存。 - GarethOwen
1
好的观点。在我对尼克答案的评论中,您会看到将位图图像嵌入SVG图像的合理性。虽然您是正确的,但编码不好且效率低下。它应该是一个单独的二进制编码文件,与SVG图像一起移动。 - chmike

4
您可以使用data: URL来嵌入图像的Base64编码版本。但这不是非常高效,我们不建议嵌入大型图像。有没有其他原因导致无法链接到另一个文件呢?

这取决于使用情况。我考虑的使用情况是复制SVG文件并且互联网访问不总是可用的(例如名片)。它还允许保持卡片的使用私密性。对于链接的图像,图像所有者可以跟踪其卡片的所有显示,这对他可能很有趣,但对于持卡人来说则不然。自包含的SVG图像是有意义的。 - chmike
如果您使用指向互联网上某个位置的绝对URL,那么这是正确的。但是,很容易使用相对URL,以便如果SVG文件是本地的,则图像也将是本地的。如果您还有一个要求,即它必须是一个单一的可再分发文件,那么这又会改变事情。 - Nick
有些情况下,您希望SVG图形是自包含的 - 即一个文件包含整个图像。在处理文件系统上的图像时,必须传输/存储多个文件以确保图像被呈现并不是一件好事 - 事情很容易失去同步或丢失。 - Minok

1
如果您想在SVG内多次使用该图像(参考):
<image id="img" xlink:href="data:image/png;base64,BASE64_DATA" />

<use href="#img" />
<use href="#img" />

0

还可以包含位图。我认为您也可以对其进行转换。


确实。我刚刚找到了这个链接:http://www.w3.org/TR/SVG/struct.html#ImageElement。不幸的是,它并没有回答我的问题,而我注意到这个问题并没有在问题中说明。我会编辑问题。 - chmike

0

我已经想到了多种绘制SVG中太空侵略者的解决方案:

第一种方法利用了具有stroke-width="1"path。通过反复停止和开始线条,我们可以通过遍历扫描线来构造位图图像。这种方法的缺点是每个“点”的y坐标向上移动了0.5个像素,因为“y”坐标被视为stroke-width="1"的中间坐标。

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<path
    stroke="black"
    fill="none"
    d="M 4 4 l 1 0
M 10 4 l 1 0
M 5 5 l 1 0
M 9 5 l 1 0
M 4 6 l 7 0
M 3 7 l 2 0
M 6 7 l 3 0
M 10 7 l 2 0
M 2 8 l 11 0
M 2 9 l 1 0
M 4 9 l 7 0
M 12 9 l 1 0
M 2 10 l 1 0
M 4 10 l 1 0
M 10 10 l 1 0
M 12 10 l 1 0
M 5 11 l 2 0
M 8 11 l 2 0"
/>
</svg>

第二种方法是通过使用带有marker-startmarker-midmarker-end属性的<marker>来实现:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
  <defs>
    <marker
      id="dot"
      viewBox="0 0 1 1"
      refX="0.5"
      refY="0.5"
      markerWidth="1"
      markerHeight="1">
      <rect width="1" height="1" />
    </marker>
  </defs>
  <polyline
    points="4 4 10 4
5 5 9 5
4 6 5 6 6 6 7 6 8 6 9 6 10 6
3 7 4 7 6 7 7 7 8 7 10 7 11 7
2 8 3 8 4 8 5 8 6 8 7 8 8 8 9 8 10 8 11 8 12 8
2 9 4 9 5 9 6 9 7 9 8 9 9 9 10 9 12 9
2 10 4 10 10 10 12 10
5 11 6 11 8 11 9 11"
    fill="none"
    stroke="none"
    marker-start="url(#dot)"
    marker-mid="url(#dot)"
    marker-end="url(#dot)" />
</svg>

第三种方法是通过定义一个<rect>,然后使用<use>重复引用它。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<g fill="none"><rect id="dot" width="1" height="1"/></g>
<g fill="black">
<use href="#dot" x="4" y="4"/>
<use href="#dot" x="10" y="4"/>
<use href="#dot" x="5" y="5"/>
<use href="#dot" x="9" y="5"/>
<use href="#dot" x="4" y="6"/>
<use href="#dot" x="5" y="6"/>
<use href="#dot" x="6" y="6"/>
<use href="#dot" x="7" y="6"/>
<use href="#dot" x="8" y="6"/>
<use href="#dot" x="9" y="6"/>
<use href="#dot" x="10" y="6"/>
<use href="#dot" x="3" y="7"/>
<use href="#dot" x="4" y="7"/>
<use href="#dot" x="6" y="7"/>
<use href="#dot" x="7" y="7"/>
<use href="#dot" x="8" y="7"/>
<use href="#dot" x="10" y="7"/>
<use href="#dot" x="11" y="7"/>
<use href="#dot" x="2" y="8"/>
<use href="#dot" x="3" y="8"/>
<use href="#dot" x="4" y="8"/>
<use href="#dot" x="5" y="8"/>
<use href="#dot" x="6" y="8"/>
<use href="#dot" x="7" y="8"/>
<use href="#dot" x="8" y="8"/>
<use href="#dot" x="9" y="8"/>
<use href="#dot" x="10" y="8"/>
<use href="#dot" x="11" y="8"/>
<use href="#dot" x="12" y="8"/>
<use href="#dot" x="2" y="9"/>
<use href="#dot" x="4" y="9"/>
<use href="#dot" x="5" y="9"/>
<use href="#dot" x="6" y="9"/>
<use href="#dot" x="7" y="9"/>
<use href="#dot" x="8" y="9"/>
<use href="#dot" x="9" y="9"/>
<use href="#dot" x="10" y="9"/>
<use href="#dot" x="12" y="9"/>
<use href="#dot" x="2" y="10"/>
<use href="#dot" x="4" y="10"/>
<use href="#dot" x="10" y="10"/>
<use href="#dot" x="12" y="10"/>
<use href="#dot" x="5" y="11"/>
<use href="#dot" x="6" y="11"/>
<use href="#dot" x="8" y="11"/>
<use href="#dot" x="9" y="11"/>
</g>
</svg>

上面的<rect> <use>解决方案的一个改进是定义可以在以后重用的二进制排列。这种风格有点让人回忆起8位编程和精灵的日子。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<g fill="none">
<g id="s0001"><rect x="3" width="1" height="1"/></g>
<g id="s0010"><rect x="2" width="1" height="1"/></g>
<g id="s0011"><rect x="2" width="2" height="1"/></g>
<g id="s0100"><rect x="1" width="1" height="1"/></g>
<g id="s0110"><rect x="1" width="2" height="1"/></g>
<g id="s1000"><rect width="1" height="1"/></g>
<g id="s1011"><rect width="1" height="1"/><rect x="2" width="2" height="1"/></g>
<g id="s1100"><rect width="2" height="1"/></g>
<g id="s1101"><rect width="2" height="1"/><rect x="2" width="1" height="1"/></g>
<g id="s1110"><rect width="3" height="1"/></g>
<g id="s1111"><rect width="4" height="1"/></g>
</g>
<g fill="black">
<use href="#s1000" x="4" y="4"/>
<use href="#s0010" x="8" y="4"/>
<use href="#s0100" x="4" y="5"/>
<use href="#s0100" x="8" y="5"/>
<use href="#s1111" x="4" y="6"/>
<use href="#s1110" x="8" y="6"/>
<use href="#s0001" x="0" y="7"/>
<use href="#s1011" x="4" y="7"/>
<use href="#s1011" x="8" y="7"/>
<use href="#s0011" x="0" y="8"/>
<use href="#s1111" x="4" y="8"/>
<use href="#s1111" x="8" y="8"/>
<use href="#s1000" x="12" y="8"/>
<use href="#s0010" x="0" y="9"/>
<use href="#s1111" x="4" y="9"/>
<use href="#s1101" x="8" y="9"/>
<use href="#s1000" x="12" y="9"/>
<use href="#s0010" x="0" y="10"/>
<use href="#s1000" x="4" y="10"/>
<use href="#s0010" x="8" y="10"/>
<use href="#s1000" x="12" y="10"/>
<use href="#s0110" x="4" y="11"/>
<use href="#s1100" x="8" y="11"/>
</g>
</svg>

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