【问题标题】:JavaScript createElementNS and SVGJavaScript createElementNS 和 SVG
【发布时间】:2011-03-30 08:54:10
【问题描述】:

我想使用 Javascript 创建内联 SVG 图形。

但是,createElementNS 函数似乎应用了一些规范化并将所有标签转换为小写。这对 HTML 来说很好,但对 XML/SVG 则不然。我使用的NS是http://www.w3.org/2000/svg

特别是我在创建元素时遇到问题。因为它将被附加为<textpath>,因此将不起作用。

我做了一些搜索,但还没有找到解决方案。

有人知道解决办法吗?

document.createElementNS("http://www.w3.org/2000/svg","textPath");

结果

<textpath></textpath>

【问题讨论】:

标签: javascript svg capitalization


【解决方案1】:

希望下面的例子对你有所帮助:

function CreateSVG() {
    var xmlns = "http://www.w3.org/2000/svg";
    var boxWidth = 300;
    var boxHeight = 300;

    var svgElem = document.createElementNS(xmlns, "svg");
    svgElem.setAttributeNS(null, "viewBox", "0 0 " + boxWidth + " " + boxHeight);
    svgElem.setAttributeNS(null, "width", boxWidth);
    svgElem.setAttributeNS(null, "height", boxHeight);
    svgElem.style.display = "block";

    var g = document.createElementNS(xmlns, "g");
    svgElem.appendChild(g);
    g.setAttributeNS(null, 'transform', 'matrix(1,0,0,-1,0,300)');

    // draw linear gradient
    var defs = document.createElementNS(xmlns, "defs");
    var grad = document.createElementNS(xmlns, "linearGradient");
    grad.setAttributeNS(null, "id", "gradient");
    grad.setAttributeNS(null, "x1", "0%");
    grad.setAttributeNS(null, "x2", "0%");
    grad.setAttributeNS(null, "y1", "100%");
    grad.setAttributeNS(null, "y2", "0%");
    var stopTop = document.createElementNS(xmlns, "stop");
    stopTop.setAttributeNS(null, "offset", "0%");
    stopTop.setAttributeNS(null, "stop-color", "#ff0000");
    grad.appendChild(stopTop);
    var stopBottom = document.createElementNS(xmlns, "stop");
    stopBottom.setAttributeNS(null, "offset", "100%");
    stopBottom.setAttributeNS(null, "stop-color", "#0000ff");
    grad.appendChild(stopBottom);
    defs.appendChild(grad);
    g.appendChild(defs);

    // draw borders
    var coords = "M 0, 0";
    coords += " l 0, 300";
    coords += " l 300, 0";
    coords += " l 0, -300";
    coords += " l -300, 0";

    var path = document.createElementNS(xmlns, "path");
    path.setAttributeNS(null, 'stroke', "#000000");
    path.setAttributeNS(null, 'stroke-width', 10);
    path.setAttributeNS(null, 'stroke-linejoin', "round");
    path.setAttributeNS(null, 'd', coords);
    path.setAttributeNS(null, 'fill', "url(#gradient)");
    path.setAttributeNS(null, 'opacity', 1.0);
    g.appendChild(path);

    var svgContainer = document.getElementById("svgContainer");
    svgContainer.appendChild(svgElem);
}
#svgContainer {
  width: 400px;
  height: 400px;
  background-color: #a0a0a0;
}
<body onload="CreateSVG()">
    <div id="svgContainer"></div>
</body>

【讨论】:

  • 感谢您的回复。根据您的回答和文本到路径的 svg 示例:http://pmast.de/svg/textToPath.svg 我创建了以下文档:http://pmast.de/svg/textToPath.html 尽管结果源看起来相同并且元素的创建遵循您的示例,但我的文档无法正常工作...我错过了什么吗?
  • 您的示例帮助我开始从 JS 创建 SVG 元素。仍然必须阅读有关 Core DOM 的 W3.org 规范文档。命名空间相当混乱。感谢您的提示。
  • 这对人们有用吗?我只是得到一个没有任何 SVG 元素的灰色框。 (Firefox 和 Chrome 一样)
【解决方案2】:

首先,使用 createElementNS,就像你正在做的那样。根据Mozilla documentation,createElement(没有 NS)自动将 HTML 文档中的元素名称小写。

其次,不要相信谷歌浏览器的“检查元素”功能。无论实际的 nodeName 是什么,它似乎都以小写形式显示每个元素。试试这个:

document.createElementNS("http://www.w3.org/2000/svg", "textPath").nodeName
// Output: "textPath"

document.createElement("textPath").nodeName
// Output: "TEXTPATH"

您的问题可能是不相关的问题。例如,此代码在 Firefox 中运行良好,但在 Chrome (12.0.742.112) 中中断:

function animateSVG() {
  var svgNS = "http://www.w3.org/2000/svg";
  var textElement = document.getElementById("TextElement");
  var amElement = document.createElementNS(svgNS, "animateMotion");
  console.log(textElement);
  console.log(amElement);
  console.log(amElement.nodeName);
  amElement.setAttribute("path", "M 0 0 L 100 100");
  amElement.setAttribute("dur", "5s");
  amElement.setAttribute("fill", "freeze");
  textElement.appendChild(amElement);
  //amElement.beginElement();
};
<body onload="animateSVG()">
  <svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <g transform="translate(100,100)">
      <text id="TextElement" x="0" y="0" style="font-family:Verdana;font-size:24">
        It's SVG!
        <!-- <animateMotion path="M 0 0 L 100 100" dur="5s" fill="freeze"/> -->
      </text>
    </g>
  </svg>
</body>

我的问题可能与 Chrome (Issue 13585) 中对 animateMotion 的错误处理有关。

您的问题可能相同,也可能是另一个问题,但请确保您没有被元素检查器愚弄。

【讨论】:

  • 您对 chrome 检查元素功能的评论为我节省了一天,谢谢
【解决方案3】:

我刚刚解决了一个类似的问题。 document.createElement(我假设是 document.createElementNS),当从 HTML 页面调用时会创建一个 HTML 节点(大小写无关紧要),而不是 xml 节点。

以下在 Chrome 中有效:

doc = document.implementation.createDocument(null, null, null); doc.createElementNS("http://www.w3.org/2000/svg","textPath");

您将获得混合大小写节点。

【讨论】:

  • document.createElementNS() 不仅创建 HTML 元素。这个答案怎么会有 5 个赞??
【解决方案4】:

给出的答案太广泛了,对我来说并没有真正的用处,我觉得它很麻烦,或者只是说假的。如果我是你,我会简单地在带有标签的 html 元素上说:

<b id="myElement"></b>

当我必须创建元素或添加信息时,我会简单地做:

document.getElementById('myElement').innerHTML = 'your stuff here'; 

希望对您有所帮助。

【讨论】:

  • 这个问题是关于 SVG,而不是 HTML。
  • @gilly3 他说得有道理——公认的答案涉及基本上从头开始构建一个 SVG DOM 元素,虽然知道如何做而且从技术上讲是更正确的答案,但并不完全实用。由于 SVG 文件中的 SVG 语法与 DOM 中的 SVG 定义语法基本相同(从 '
  • 这是一个非常具体的用例 - 将整个 SVG 绘图标记作为字符串,并将其按原样附加到 HTML 元素。问题是专门询问如何将 SVG 元素添加到现有绘图中。现在,今天您可以在某些浏览器中编写 SVG 元素的 innerHTML,但 that functionality is new, and has only been available since earlier this year。今天,在 IE 中以及在所有浏览器中,向现有绘图添加元素的唯一方法是通过createElementNS()
猜你喜欢
  • 1970-01-01
  • 2011-12-31
  • 1970-01-01
  • 2015-03-07
  • 2016-09-09
  • 2023-03-25
  • 2013-08-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多