【问题标题】:Load an SVG image where the elements become part of the DOM加载元素成为 DOM 一部分的 SVG 图像
【发布时间】:2021-12-16 10:19:17
【问题描述】:

考虑这个简单的页面:

<html>
<body>
   <svg width="250" height="250">
      <g>
         <path id="foo" d="M20,230 Q40,205 50,230 T90,230" stroke="red" stroke-width="3" fill="none" onclick="setBlue()" />
      </g>
   </svg>
   <script>
      function setBlue() {
         document.getElementById("foo").setAttribute("stroke", "blue");
      }
   </script>
</body>
</html>

它将显示一条红色波浪线。如果单击该线,它将变为蓝色。这表明 JavaScript 功能正在这个 SVG 对象中运行,并且路径元素 foo 已添加到 DOM 本身。

现在改为加载浏览器可以缓存的静态 SVG:

<img width="250" height="250" src="images/somesvg.svg" />

嵌入的 JavaScript 没有命中。通过 JavaScript 或 jQuery 向 DOM 请求 foo 不会返回任何内容。

这是否意味着在 SVG 中命名元素或添加 JavaScript 功能的唯一方法是在 HTML 本身中呈现 SVG?如果我可以将 ID 添加到 SVG 文件中的路径然后访问它们,我可以显着缩短页面。

【问题讨论】:

  • “这是否意味着在 SVG 中命名元素或添加 JavaScript 功能的唯一方法是在 HTML 本身中渲染 SVG?” - 是的,使用 img 标签渲染的 svg 将像光栅图像一样被静态处理。如果您不能将它们内联在文件中,最好的方法 imo 是使用 javascript 来获取并将它们作为内联 svgs 注入,但请参阅此处的讨论以获取替代方案和 stackoverflow.com/questions/4476526/… ,特别是关于 标签。
  • this 你在找什么?
  • 您可以通过&lt;use xlink:href="external.svg#id1"&gt;&lt;/use&gt;从外部svg添加任何元素。这可能是 DOM 中 svg 中的整个 svg。

标签: html svg dom


【解决方案1】:

如果是外部的*.svg文件,一个原生的Web Component&lt;load-file&gt;可以获取它并注入到DOM中;在 shadowDOM 中或替换 &lt;load-file&gt; 元素,从而成为 DOM 的一部分,您可以使用 CSS 访问和设置样式。

customElements.define("load-file", class extends HTMLElement {

  // declare default connectedCallback as async so await can be used
  async connectedCallback(
    // call connectedCallback with parameter to *replace* SVG (of <load-file> persists)
    src = this.getAttribute("src"),
    // attach a shadowRoot if none exists (prevents displaying error when moving Nodes)
    shadowRoot = this.shadowRoot || this.attachShadow({mode:"open"})
  ) {
      // load SVG file from src="" async, parse to text, add to shadowRoot.innerHTML
    shadowRoot.innerHTML = await (await fetch(src)).text()

    // append optional <tag [shadowRoot]> Elements from inside <load-svg> after parsed <svg>
    shadowRoot.append(...this.querySelectorAll("[shadowRoot]"))

    // if "replaceWith" attribute 
    // then replace <load-svg> with loaded content <load-svg>
    // childNodes instead of children to include #textNodes also
    this.hasAttribute("replaceWith") && this.replaceWith(...shadowRoot.childNodes)
  }
})

Dev.To 中的完整解释发帖:〈load-file〉Web Component, add external content to the DOM

【讨论】:

    【解决方案2】:

    正如 @diopside 和 @RobertLongson 在 cmets 中提到的那样,这里的问题以不同的方式提出:Do I use <img>, <object>, or <embed> for SVG files?

    解决方案是使用 &lt;object&gt; 并将 SVG 嵌入其中。现在我可以与之交互,但浏览器不需要在每次页面加载时都重新加载图像。

    【讨论】:

      猜你喜欢
      • 2019-03-26
      • 2017-04-03
      • 2011-01-23
      • 2018-08-08
      • 1970-01-01
      • 2018-07-15
      • 1970-01-01
      • 2012-05-07
      • 2021-06-10
      相关资源
      最近更新 更多