SVG fill="url(#)" 的问题

JS_*_*ler 5 svg linear-gradients

我正在动态创建几个具有相同结构的 SVG。

我遇到的问题是我必须通过它们的 ID 引用渐变,因此当有多个 SVG 时,ID 会发生冲突并导致意外结果。有没有办法通过 ID 引用其他 SVG 元素?我可以将选择限制在 SVG 元素内吗?


第一部分

在一个简单的例子中,我有两个具有相同结构的 SVG——它们将由一些 javascript 动态创建。问题:请注意,第二个 SVG 使用第一个的渐变:

<div>
  This is the first SVG, it defines "#Gradient" as red-black.
  <br>
  <svg viewBox="0 0 10 10" width="50" height="50" style="border: 1px solid black;">
    <defs>
      <linearGradient id="Gradient" x1="0%" x2="0%" y1="0%" y2="100%">
        <stop offset="0%" stop-color="red"/>
        <stop offset="100%" stop-color="black"/>
      </linearGradient>
    </defs>
    <circle cx="5" cy="5" r="5" fill="url('#Gradient')" />
  </svg>
</div>
    
<div>
  This is the second SVG. It ends up displaying a red-black circle instead of red-green.
  <br>
  <svg viewBox="0 0 10 10" width="50" height="50" style="border: 1px solid black;">
    <defs>
      <linearGradient id="Gradient" x1="0%" x2="0%" y1="0%" y2="100%">
        <stop offset="0%" stop-color="red"/>
        <stop offset="100%" stop-color="green"/>
      </linearGradient>
    </defs>
    <circle cx="5" cy="5" r="5" fill="url('#Gradient')" />
  </svg>
</div>
Run Code Online (Sandbox Code Playgroud)

真的需要在每次创建 SVG 时插入一个唯一 ID 以便它们可以很好地协同工作吗?


第二部分

现在,假设我其实希望我所有的SVGs使用相同的linearGradient对象。那我们就说清楚吧。我们将只定义一次并在所有其他 SVG 中重用它:

<div>
  Let's define the linearGradient once, and use it later. No need to display this.
  <svg style="display: none;">
    <defs>
      <linearGradient id="Gradient" x1="0%" x2="0%" y1="0%" y2="100%">
        <stop offset="0%" stop-color="red"/>
        <stop offset="100%" stop-color="black"/>
      </linearGradient>
    </defs>
  </svg>
</div>

<div>
  Ok, let's use the linearGradient defined above. This won't work unless the above is visible -- why?
  <svg viewBox="0 0 10 10" width="50" height="50" style="border: 1px solid black;">
    <circle cx="5" cy="5" r="5" fill="url('#Gradient')" />
  </svg>
  <svg viewBox="0 0 10 10" width="50" height="50" style="border: 1px solid black;">
    <circle cx="5" cy="5" r="5" fill="url('#Gradient')" />
  </svg>
</div>
Run Code Online (Sandbox Code Playgroud)

这对我(Chrome)不起作用,显然是因为定义的 SVG 位于带有"display: none;". 因此,在引用其他 SVG 元素时,它们必须“可见”才能使用。这样做的最佳方法是什么——我应该将定义的 SVG 移出屏幕吗?

Con*_*sis 0

就我个人而言,我使用以下方法为每个 SVG 元素生成一个唯一的 ID:

const id = "loadericon-" + Math.random().toString(16).slice(2);
Run Code Online (Sandbox Code Playgroud)

在我的 SVG 中:

      <defs>
        <rect
          id={id}
          width={6}
          height={14}
          x={46.5}
          y={45}
          rx={2}
          ry={2}
          transform="translate(0 -30)"
        />
      </defs>
Run Code Online (Sandbox Code Playgroud)

注意:我使用React,这样做非常方便。