从字符串创建一个SVG DOM元素

41

我该如何通过一个String创建一个SVG DOM元素?

例如:

var svgStr = '<svg width="500" height="400" xmlns="http://www.w3.org/2000/svg"><!-- Created with Method Draw - http://github.com/duopixel/Method-Draw/ --><g><title>background</title><rect fill="#fff" id="canvas_background" height="402" width="502" y="-1" x="-1"/><g display="none" overflow="visible" y="0" x="0" height="100%" width="100%" id="canvasGrid"><rect fill="url(#gridpattern)" stroke-width="0" y="0" x="0" height="100%" width="100%"/></g></g><g><title>Layer 1</title><path id="svg_1" d="m118,242l64,-153l63,157c0,0 45,-71 49,-68c4,3 11,146 12,146c1,0 -173,-7 -173,-7c0,0 -61,-72 -61,-72c0,0 110,-156 46,-3z" fill-opacity="0.7" stroke-width="2" stroke="#995757" fill="#995757"/></g></svg>';

那是什么语言?(var 不是 SVG 或 XML 的一部分;它是 JavaScript 吗?还是其他语言?)请编辑您的问题并添加正确的标签。 - helderdarocha
@helderdarocha 刚刚完成了,抱歉。这是用 JavaScript 编写的。 - nicholaswmin
1
我发布了一个可能的答案。你可以在JSFiddle上尝试它。 - helderdarocha
6个回答

57

您可以使用DOMParser来解析XML字符串。

var parser = new DOMParser();
var doc = parser.parseFromString(stringContainingXMLSource, "image/svg+xml");

解析后字符串的根元素将是doc.documentElement。

为了在不同浏览器中正常工作,您需要设置HTML命名空间,即您的字符串需要像这样...

var svg2='<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" ...

在我的情况下,使用DOM解析器使SVG的渲染非常缓慢和滞后。我尝试附加SVG(而不是作为字符串),并且没有性能问题。有关此事的任何信息?还有,IE对此的支持如何? - Tushar Shukla
请单独提出新问题,尽管 IE 支持此功能。 - Robert Longson

20

假设您正在使用JavaScript,您可以通过DOM API获取现有元素并将该字符串简单地传递为其innerHTML

var svg2 = "<svg ...> ... </svg>";
var container = document.getElementById("container");
container.innerHTML = svg2;

请查看:JSFiddle


我不确定IE的早期版本,但它当前版本肯定可以运行(我不能测试因为我在Mac上)。它还能在Firefox 29.0.1,Chrome 35.0和Opera 22.0上运行。 - helderdarocha
4
注意,如果使用 .innerHTML += 来添加内容,会清除掉内部元素上的任何事件监听器。这让我花费了很长时间来调试找出问题所在。 - Nic Scozzaro
小心不要让你的应用程序受到DOM XSS攻击--请参见https://web.dev/trusted-types/#rewrite-the-offending-code。 - Ramses

2

不要使用返回到父级功能,你可以使用以下技巧。

const template = `
  <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path d="M1 13L13 1M1 1L13 13" stroke="#111827" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
  </svg>`

  const span = document.createElement('span')
  span.innerHTML = template
  return span.firstChild

2

我正在构建SVG图表,并需要让用户传递任何SVG来将其转换为图表注释。解决方案是:

index.html - 我要附加子SVG的根SVG元素

<svg id="chart_SVG" width="900" height="600" role="img" xmlns="http://www.w3.org/2000/svg"></svg>

api.ts - 用 TypeScript 编写的添加注释的 API。x、y 是放置注释的坐标。

function drawAnnotation(x: number, y: number, svgContent: string, svgId: string): SVGElement {
  const svgRoot = document.getElementById("chart_SVG");
  const svgNode = document.createRange().createContextualFragment(svgString);
  svgRoot.appendChild(svgNode);
  const newNode = this.svgRoot.lastChild as SVGElement;
  newNode.id = svgId;
  newNode.setAttribute("x", x.toString());
  newNode.setAttribute("y", y.toString());
  return newNode;
}

example.ts

drawAnnotation(
  100,
  100,
  '<svg><g><rect x="0" y="0" width="100%" height="100%" stroke="red" stroke-width="10" fill="orange"/><text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" font-family="Verdana" font-size="24" fill="blue">TEXT</text></g></svg>',
  "myNewNode"
)

1

0
这是一个JS函数示例,用于返回一个SVGELement实例:
function svgElementFromString(str) {
    const div = document.createElement('DIV');
    div.innerHTML = str;
    const svg = div.querySelector('svg');

    if (!svg) {
      throw Error('<svg> tag not found');
    }

    return svg;
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接