JavaScript createElementNS 和 SVG

IT技术 javascript svg capitalization
2021-02-22 09:31:37

我想使用 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个回答

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

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>

您的示例帮助我开始从 JS 创建 SVG 元素。仍然需要阅读有关 Core DOM 的 W3.org 规范文档。命名空间相当混乱。谢谢你的提示。
2021-04-17 09:31:37
这对人有用吗?我只是得到一个没有任何 SVG 元素的灰色框。(Firefox 和 Chrome 都一样)
2021-04-24 09:31:37
感谢您的回复。根据您的回答和文本到路径 svg 示例:http : //pmast.de/svg/textToPath.svg 我创建了以下文档:http : //pmast.de/svg/textToPath.html 虽然结果源似乎相同,元素的创建遵循您的示例,我的文档不起作用......我错过了什么吗?
2021-04-25 09:31:37

首先,像您一样使用 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)。

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

你对 chromes 检查元素功能的评论拯救了我的一天,谢谢
2021-05-13 09:31:37

我刚刚解决了一个类似的问题。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个赞??
2021-04-18 09:31:37

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

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

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

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

我希望那是有帮助的。

@gilly3 不过,他有一个观点——接受的答案涉及基本上从头开始构建一个 SVG DOM 元素,虽然很清楚如何做并且从技术上讲是更正确的答案,但并不完全实用。由于 SVG 文件中的 SVG 语法与 DOM 中的 SVG 定义语法基本相同(从 '<svg' 子字符串开始),采用 span 或 b 等容器元素并将其 innerHTML 属性设置为更实用原始 SVG 数据——浏览器会以这种方式为您处理硬解析和构建工作。我会说这是一个有效的“快速修复”答案
2021-04-16 09:31:37
这是一个非常具体的用例 - 将整个 SVG 绘图标记作为字符串,并将其按原样附加到 HTML 元素。问题是专门询问有关将 SVG 元素添加到现有绘图的问题。现在,今天您可以innerHTML在某些浏览器中编写SVG 元素的 ,但该功能是新功能,并且自今年早些时候才可用如今,在 IE 中以及在提出此问题时的所有浏览器中,将元素添加到现有绘图的唯一方法是通过createElementNS().
2021-05-02 09:31:37
这个问题是关于 SVG,而不是 HTML。
2021-05-13 09:31:37