使用重复的嵌套 SVG 元素

Working with duplicated nested SVG elements

我在使用 snap.svg 时遇到了以下问题。

我想在主元素中使用嵌套的 SVG 元素。假设其中一个嵌套的结构如下:

<svg width="71" height="101" viewBox="0 0 71 101">
<defs>
    <rect id="a" width="70" height="100" rx="5"/>
    <mask id="d" width="70" height="100" x="0" y="0" fill="#fff">
    <use xlink:href="#a"/>
    </mask>
    <rect id="b" width="70" height="100" rx="5"/>
    <mask id="e" width="70" height="100" x="0" y="0" fill="#fff">
    <use xlink:href="#b"/>
    </mask>
    <pattern id="f" width="6" height="5" x="-6" y="-5" patternUnits="userSpaceOnUse">
    <use transform="scale(.5)" xlink:href="#tipstercard-c"/>
    </pattern>
    <image id="c" width="12" height="10" xlink:href="data:image/png;base64,..."/>
</defs>
<g fill="none" fill-rule="evenodd" transform="translate(.338 .194)">
    <use fill="#212120" stroke="#FFF" stroke-width="4" mask="url(#tipstercard-d)" xlink:href="#a"/>
    <use fill="url(#f)" fill-opacity=".1" stroke="#FFF" stroke-width="4" mask="url(#e)" style="mix-blend-mode:luminosity" xlink:href="#b"/>
    <path fill="#FFF" d="M20.22 47.784v1.53h-1.344v2.923c0 .593.013.937.04 1.035a.42.42 0 0 0 .174.241c.091.064.2>...

我尝试像 fragments['card'].select('svg').clone(); 那样做某事,但这导致:TypeError: Failed to construct 'URL': Please use the 'new' operator, this DOM object constructor cannot be called as a function.

我也尝试关注 fragments['card'].select('svg').toDefs();,但这导致:DOMException: Failed to execute 'appendChild' on 'Node': The new child element contains the parent.

使用 snap 的可能方法是什么?

编辑 好像我需要使用:

  Surface.append(fragments['card']);
  const Card = Surface.select('#card');
  Card.toDefs();
  const CardDef = Surface.select('#card');
  CardDef.use().attr({...});

现在的问题是为什么这行不通 fragments['card'].select('svg').toDefs(); 而上面的代码却行得通?为什么我不能直接使用fragments['card'].select('svg')

片段没有 Snap 方法的概念,因此像 clone() 这样的方法将不起作用。首先需要将它们附加到 DOM。此外,DOM 中的片段并不完整,因此 DOM SVG 元素可用的一些常见 svg 方法存在问题。

所以像 fragment.select('svg').clone() 这样的东西是行不通的(因为 clone 是一种 Snap 方法)。首先你需要 'Snapify' 它(将它变成一个 Snap 元素,一个 svg 元素的包装器)。

因此您需要执行以下操作..首先将其添加到 DOM...

Surface.append( fragment.select('svg') );

现在它在 DOM 中,您可以对其进行 Snapify 并克隆它(因为我们现在可以使用此元素的 Snap 方法)。

Surface.select('someId').clone();

请注意,如果您在某处有一个 DOM 元素,您也可以将它变成一个 Snap 元素,方法是

var snapElement = Snap( someDomElement );

这使 DOM 元素保持原样,但只是在其周围添加了一个 Snap 包装器,并且 returns 这是 Snap 元素。

所以您自己找到了正确的代码,主要答案是您的元素在尝试对其调用方法(或附加到 DOM 时)不是 Snap 元素。

注意:您可以在不将片段添加到 DOM 的情况下对片段进行 Snapify,但它不会给您带来任何新方法,除非它在主 DOM 我认为,但可以仅存储对稍后将追加的元素的引用很方便。