是否可以从现有的 SVG 文件创建 DOM 节点(然后将其 appendChild 到某个 DOM 元素中)? [英] Is it possible to create a DOM node (and then appendChild it into some DOM element) from an existing SVG file?

查看:47
本文介绍了是否可以从现有的 SVG 文件创建 DOM 节点(然后将其 appendChild 到某个 DOM 元素中)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果有人帮助我解决以下问题,我将不胜感激.渲染的 DOM 树中有一个 span 元素,其中包含一些 svg 元素:

I would really appreciate if somebody helps me to solve the following problem. There is a span-element inside of rendered DOM tree which contains some svg-element:

<...>
  <span>
    <svg>
      <path d="..."></path>
    </svg>
  </span>
<...>

我需要用我的自定义 SVG 图像替换给定的 svg 元素.最好使用现有的 SVG 文件作为生成新 svg 元素的源,然后将其 appendChild 到父 span 元素中.不幸的是,我无法弄清楚如何自己做到这一点.当我尝试从现有的 SVG 文件导入必要的图像并将其 appendChild 到 span 元素时,我遇到以下错误:

I need to replace the given svg-element with my custom SVG-image. It would be perfect to use an existing SVG-file as a source for generating a new svg-element and then appendChild it into the parent span-element. Unfotunatelly I can't figure out how to do that on my own. When I'm trying to import the necessary image from the existing SVG-file and appendChild it into the span-element I encounter the following error:

Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'

我目前发现的唯一 JS 解决方案是创建一个函数,该函数通过字符串重新创建我的 SVG 图像字符串,如下所示:

The only JS-solution I've found in moment is to create a function which recreates my SVG-image string by string like so:

const customizeSelectionDropdownSVG = () => {
    const createNewSVG = () => {
      const xmlns = "http://www.w3.org/2000/svg";
      const boxWidth = 16;
      const boxHeight = 16;

      const newSVG = document.createElementNS(xmlns, "svg");
      newSVG.setAttributeNS(null, "viewBox", `0 0 ${boxWidth} ${boxHeight}`);
      newSVG.setAttributeNS(null, "width", boxWidth);
      newSVG.setAttributeNS(null, "height", boxHeight);
      newSVG.style.display = "block";

      const path = document.createElementNS(xmlns, "path");
      path.setAttributeNS(null, "class", "b");
      path.setAttributeNS(null, "d", "M160.294,147.293l-2.829-2.829a1,1,0,0,0-1.414,1.415L158.173,148l-2.122,2.121a1,1,0,0,0,1.414,1.415l2.829-2.829A1,1,0,0,0,160.294,147.293Z");
      path.setAttributeNS(null, "transform", "translate(-150 -140)");

      newSVG.appendChild(path);
      return newSVG;
    };
    const customizedSelectionDropdownSVG = createNewSVG();

    const selectorValue = "span";
    const svgContainer = document.querySelectorAll(selectorValue);
    const oldSVG = document.querySelectorAll(`${selectorValue} svg`);

    if (oldSVG && svgContainer) {
      for (let i = 0; i < oldSVG.length; i++) {
        oldSVG[i].remove();
      }
      for (let j = 0; j < svgContainer.length; j++) {
        svgContainer[j].appendChild(customizedSelectionDropdownSVG);
      }
    }
  };

是的,它有效!但看起来很冗长.所以我想知道是否有更优化的解决方案?预先感谢您的帮助.

And yeah, it works! But looks verbose. So I'm wondering if there is more optimal solution? Thanks in advance for your help.

推荐答案

最好使用现有的 SVG 文件作为生成新 svg 元素的源

would be perfect to use an existing SVG-file as a source for generating a new svg-element

  • 创建一个 vanilla W3C 标准 Web 组件
  • 将 SVG src 加载为文本
  • 将其设置为 innerHTML
    • create a vanilla W3C standard Web Component <load-svg>
    • Load SVG src as text
    • set it as the <load-svg> innerHTML
    • <load-svg src="https://load-file.github.io/heart.svg"></load-svg>
      
      <script>
      customElements.define("load-svg", class extends HTMLElement {
        async connectedCallback(  src = this.getAttribute("src")  ) {
          this.innerHTML = await (await fetch( src )).text()
        }
      })
      </script>
      
      <style>
        svg { height: 180px } /* fit in SO snippet window */
      </style>

      • 如果您需要加载其他内容,请调用:
      document.querySelector("load-svg")
              .connectedCallback("https://load-file.github.io/heart.svg")
      

      文档和更高级的用法:

      https://dev.to/dannyengelman/load-file-web-component-add-external-content-to-the-dom-1nd

      这篇关于是否可以从现有的 SVG 文件创建 DOM 节点(然后将其 appendChild 到某个 DOM 元素中)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆