JavaScript createElement and SVG

╄→гoц情女王★ 提交于 2019-12-17 06:38:29

问题


I want to create inline SVG graphics using Javascript.

However, it seems like createElementNS function applies some normalization and transforms all tags to lowercase. That is fine for HTML but not for XML/SVG. The NS I used is http://www.w3.org/2000/svg.

In particular I have problems creating a element. As it will be appended as an thus will not work.

I did some search but could not find a solution yet.

Does anybody know a solution?

Thanks a lot!

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

results in

<textpath></textpath>

回答1:


I hope, the following example will help you:

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>



回答2:


Firstly, use createElementNS, as you are doing. createElement (without NS) automatically lowercases element names inside HTML documents, according to the Mozilla documentation.

Secondly, don't trust Google Chrome's "Inspect Element" feature here. It seems to display every element in lowercase, no matter what the actual nodeName is. Try this:

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

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

Your problem might be an unrelated issue. For example, this code works fine in Firefox, but breaks in 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>

My issue probably has something to do with the broken handling of animateMotion in Chrome (Issue 13585).

Your issue might be the same, or it might be another issue, but make sure you're not being fooled by the element inspector.




回答3:


I have just resolved a similar problem. document.createElement (and I assume document.createElementNS), when called from a HTML page creates a HTML node (where case doesnt matter), not an xml node.

The following works in Chrome:

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

you will get your mixed case node.




回答4:


the answer given is too extensive and not really useful to me and i find it to much troublesome or to simply say bogus. If i were you, i would simple have on element in html with tag say:

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

and when i have to create element or add information i would simply do:

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

I Hope that was helpful.



来源:https://stackoverflow.com/questions/3492322/javascript-createelement-and-svg

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!