加载 SVG 图像,其中元素成为 DOM 的一部分

Load an SVG image where the elements become part of the DOM

考虑这个简单的页面:

<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 returns 什么都不问 DOM foo

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

如果是外部 *.svg 文件,本机 Web 组件 <load-file> 可以 获取 并将其注入 DOM;在 shadowDOM 中或替换 <load-file> 元素,从而成为 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 post 中的完整解释:〈load-file〉Web Component, add external content to the DOM

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

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