SVG <symbol>实例化后只显示部分或不显示的问题

2,076 阅读1分钟

<symbol>标签是svg中用于复用图元的标签,类似于一份模板,通过<use>标签进行实例化。

具体用法请移步官方文档:symbol - svg - MDN

我们来看一个简单的例子。

我们用path绘制一个五角星:

<svg 
    width="300"
    height="300"
    style="border: 1px solid #acc;margin: 10px;"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
>
    <path d="M 100,0 L160,180 L10,60 L190,60 L40,180 Z" fill="orange" stroke="black" stroke-width="3" />
</svg>

image-20210714233156467.png

如果我们想要复制多份,就可以把这个path作为模板:

<svg 
    width="300"
    height="300"
    style="border: 1px solid #acc;margin: 10px;"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
>
    <symbol id="pentagram" viewBox="0 0 300 300">
        <path d="M 100,0 L160,180 L10,60 L190,60 L40,180 Z" fill="orange" stroke="black" stroke-width="3" />
    </symbol>

    <use xlink:href="#pentagram" width="100" height="100" />
    <use xlink:href="#pentagram" x="50" y="50" width="150" height="150" />
    <use xlink:href="#pentagram" x="150" y="150" width="200" height="200" />
</svg>

image-20210714235521087.png

现在,我们调整一下<symbol>模板的位置(可以通过任何方法来调整),这里我通过修改viewBox来实现偏移:

<symbol id="pentagram" viewBox="90 90 300 300">
    <path d="M 100,0 L160,180 L10,60 L190,60 L40,180 Z" fill="orange" stroke="black" stroke-width="3" />
</symbol>

为了适应之前的图形坐标,我们把实例的x和y也偏移(90, 90),同时注意缩放的影响:

<svg 
    width="300"
    height="300"
    style="border: 1px solid #acc;margin: 10px;"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
>
    <symbol id="pentagram" viewBox="90 90 300 300">
        <path d="M 100,0 L160,180 L10,60 L190,60 L40,180 Z" fill="orange" stroke="black" stroke-width="3" />
    </symbol>

    <use xlink:href="#pentagram" transform="translate(30,30)" width="100" height="100" />
    <use xlink:href="#pentagram" transform="translate(45,45)" x="50" y="50" width="150" height="150" />
    <use xlink:href="#pentagram" transform="translate(60,60)" x="150" y="150" width="200" height="200" />
</svg>

然后我们观察图形:

image-20210715000355569.png

发现图形显示不完整,这就是我所遇到的问题,有时候<use>实例化后图形未显示或者显示不完整,一开始我以为是宽高不够导致显示不完整,实则不是,因为我们只改动了<symmbol>的偏移,经过测试发现,虽然<symbol>模板不会渲染出来,但是如果这个模板在当前画布处于可视区域外的部分就不能被正常渲染出来,这是<symbol>模板的一个特点,至于为什么这样设计,就不得而知了。

我们把修改的<symbol>直接放到画布上,就可以看出来:

<svg 
    width="300"
    height="300"
    style="border: 1px solid #acc;margin: 10px;"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    viewBox="90 90 300 300"
>
    <path d="M 100,0 L160,180 L10,60 L190,60 L40,180 Z" fill="orange" stroke="black" stroke-width="3" />
</svg>

image-20210715000722798.png

结论就是,当模板在画布视野中只显示一部分时,渲染的实例也只会显示视野内的那部分。