46

我想使用 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>
4

4 回答 4

69

我希望,以下示例对您有所帮助:

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>

于 2010-08-16T11:07:19.223 回答
14

首先,使用 createElementNS,就像你正在做的那样。根据Mozilla 文档,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 中对 animateMotion 的错误处理有关(问题 13585)。

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

于 2011-07-06T15:16:49.670 回答
2

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

以下适用于 Chrome:

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

你会得到你的混合大小写节点。

于 2012-10-17T03:24:24.873 回答
-2

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

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

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

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

我希望这会有所帮助。

于 2011-05-19T17:43:58.560 回答