【问题标题】:How to reuse an embedded SVG element in the same page?如何在同一页面中重用嵌入的 SVG 元素?
【发布时间】:2021-05-27 16:40:20
【问题描述】:

我有一个带有嵌入式 SVG 图标元素的简单 HTML5 页面。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=">
  </head>
  <body>
    <h1>
      <span>ABC</span>
      <svg id="move-icon"
           width="0.7em" height="0.7em"
           viewBox="0 0 10 10"
           style="display: inline-block">
        <defs>
          <marker id="arrow-end-marker"
                  viewBox="0 0 10 10" refX="0" refY="5"
                  markerHeight="3"
                  orient="auto">
            <polygon points="0 0 10 5 0 10" />
	  </marker>
        </defs>
        <line x1="5" y1="5" x2="5" y2="7"
              stroke="black" stroke-width="0.03em"
              marker-end="url(#arrow-end-marker)" />
        <line x1="5" y1="5" x2="3" y2="5"
              stroke="black" stroke-width="0.03em"
              marker-end="url(#arrow-end-marker)" />
        <line x1="5" y1="5" x2="5" y2="3"
              stroke="black" stroke-width="0.03em"
              marker-end="url(#arrow-end-marker)" />
        <line x1="5" y1="5" x2="7" y2="5"
              stroke="black" stroke-width="0.03em"
              marker-end="url(#arrow-end-marker)" />
      </svg>
    </h1>
    <p>abc</p>
    <h2>
      <span>DEF</span>
      <!-- reuse here -->&#10067;
    </h2>
    <p>def</p>
  </body>
</html>

现在我想在第二个标题中重用嵌入的 SVG 图标。如何做到这一点?

【问题讨论】:

  • 如果它是内联的,那么你不能引用它。所以你必须克隆它。更好的方法是使用 svg 作为背景图形。这样你就可以在你的样式中指定一次,但这确实不是内联的。
  • @arkascha 我想为图标添加事件处理程序。我不确定,如果使用背景图片可以做到这一点?
  • 显然不适用于背景元素。然后尝试使用 ::after 或 ::before` 伪元素。您可以使用 svg 作为背景,指定特定大小并将 js 处理程序附加到伪元素。或者您只需将 svg 引用为图像。只会加载一次,因为它在本地缓存并且还允许附加事件处理程序。
  • @arkascha 不可能将事件处理程序附加到伪元素,因为它们也没有 DOM 节点。
  • 这也是真的,是的。但是你不能在伪元素中放置一个透明元素,比如透明跨度并附加一个处理程序吗?

标签: html svg


【解决方案1】:

symbol + use + href="#symbol-id"

定义一个符号一次,并在其他svg文档中使用它

<!-- define symbol in hidden svg document -->
<svg style="display: none" version="2.0">
  <defs>
    <symbol id="circle-arrow-left" viewbox="0 -10 100 110">
      <path d="m 20 80 A 40 40 0 1 0 20 20"
        fill="none" stroke="#000" stroke-width="10" />
      <path d="M 10 0 v 40 h 40"
        fill="#000" />
    </symbol>
  </defs>
  <!-- to make the circle-arrow-left.svg file
       also usable as image: -->
  <use href="#circle-arrow-left"/>
</svg>

<!-- use symbol of external svg document -->
<button>
  <svg width="50" height="50" version="2.0">
    <use href="#circle-arrow-left" />
  </svg>
</button>

<!-- transform symbol with horizontal flip -->
<button>
  <svg style="transform: scale(-1, 1)" width="50" height="50" version="2.0">
    <use href="#circle-arrow-left" />
  </svg>
</button>

更改样式:将新样式添加到使用符号的位置:

<svg style="fill: red"><use href="#s1"/></svg>

<svg class="some-class"><use href="#s2"/></svg>

inkscape 支持 &lt;svg version="2.0"&gt;&lt;use href="#some-id"/&gt;
对于 svg 版本 1.1,我们需要 &lt;svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink"&gt;&lt;use xlink:href="#some-id"/&gt;

相关:

https://css-tricks.com/svg-symbol-good-choice-icons/

https://css-tricks.com/svg-use-with-external-reference-take-2/

【讨论】:

  • 是的,xlink:href 已弃用,取而代之的是 href developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href
  • 这个答案说创建了一个单独的文档。我没有看到这种情况发生,所以它需要一个解释。这个 html 真的有一个新的 DOCUMENT 节点吗?
  • "这个 html 真的有一个新的 DOCUMENT 节点吗?" - 我们有一个 &lt;html&gt; 文档,其中包含多个 &lt;svg&gt; 文档。每个&lt;svg&gt; 文档都可以引用兄弟&lt;svg&gt; 文档的符号。可以在&lt;svg&gt;&lt;use&gt; 之前或之后定义符号
【解决方案2】:

您可以将 SVG 保存到文件中并直接在 标签中使用它。像这样

<img src="toto.svg" alt="toto description">

【讨论】:

  • 我试过了,在我看来,我无法定义,SVG 图标的大小应该是 0.7em x 0.7em。 img 标签只允许像素单位。
  • 如果您这样做,您的 SVG 将超出页面的 DOM。这意味着您不能使用页面中的 CSS 来更改您的 SVG 内容。嵌入的 SVG 基本上可以在 dom 中重用父级的颜色(但如果您愿意,还可以更多)
【解决方案3】:

我现在有一个解决方案,但我不知道为什么会这样。可以定义一个template,它可以被克隆。但是克隆意味着复制id 属性。这意味着它们不再是独一无二的。但是在marker-end 中引用它们似乎仍然是可能的。这有点奇怪,我不确定遵循这条路线是否明智。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=">
  </head>
  <body>
    <h1>
      <span class="movable">ABC</span>
    </h1>
    <p>abc</p>
    <h2>
      <span class="movable">DEF</span>
    </h2>
    <p>def</p>
    <template id="move-icon">
      <svg width="0.7em" height="0.7em"
           viewBox="0 0 10 10"
           style="display: inline-block; vertical-align: baseline">
        <defs>
          <marker id="arrow-end-marker"
                  viewBox="0 0 10 10" refX="0" refY="5"
                  markerHeight="3"
                  orient="auto">
            <polygon points="0 0 10 5 0 10" />
	  </marker>
        </defs>
        <line x1="5" y1="5" x2="5" y2="7"
              stroke="black" stroke-width="0.03em"
              marker-end="url(#arrow-end-marker)" />
        <line x1="5" y1="5" x2="3" y2="5"
              stroke="black" stroke-width="0.03em"
              marker-end="url(#arrow-end-marker)" />
        <line x1="5" y1="5" x2="5" y2="3"
              stroke="black" stroke-width="0.03em"
              marker-end="url(#arrow-end-marker)" />
        <line x1="5" y1="5" x2="7" y2="5"
              stroke="black" stroke-width="0.03em"
              marker-end="url(#arrow-end-marker)" />
      </svg>
    </template>
    <script>
      (function() {
         var icon = document.querySelector('#move-icon');
         var spans = document.querySelectorAll('span.movable');
         for (var i = 0; i < spans.length; i += 1)
           spans[i].parentNode.appendChild (icon.content.cloneNode(true));
       })();
    </script>
  </body>
</html>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-26
    • 1970-01-01
    • 2012-11-26
    • 1970-01-01
    • 1970-01-01
    • 2016-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多