Подтвердить что ты не робот

JavaScript createElement и SVG

Я хочу создать встроенную графику SVG с помощью Javascript.

Однако, похоже, что функция createElementNS применяет некоторую нормализацию и преобразует все теги в нижний регистр. Это хорошо для HTML, но не для XML/SVG. Я использовал NS, http://www.w3.org/2000/svg.

В частности, у меня возникают проблемы с созданием элемента. Поскольку он будет добавлен как, таким образом, не будет работать.

Я сделал поиск, но не смог найти решение.

Кто-нибудь знает решение?

Спасибо большое!

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

приводит к

<textpath></textpath>
4b9b3361

Ответ 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>

Ответ 2

Во-первых, используйте createElementNS, как вы это делаете. createElement (без NS) автоматически уменьшает имена элементов внутри документов HTML, в соответствии с документацией Mozilla.

Во-вторых, не доверяйте функции Google Check Inspect Element. Кажется, он отображает каждый элемент в нижнем регистре, независимо от фактического имени узла. Попробуйте следующее:

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

Ваша проблема может быть несвязанной проблемой. Например, этот код отлично работает в Firefox, но разбивается на Chrome (12.0.742.112):

<html>
  <head>
      <script>
        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();
        };
      </script>
  </head>
  <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 SVG!
          <!-- <animateMotion path="M 0 0 L 100 100" dur="5s" fill="freeze"/> -->
        </text>
      </g>
    </svg>
  </body>
</html>

Моя проблема, вероятно, имеет какое-то отношение к нарушенной обработке animateMotion в Chrome (Проблема 13585).

Ваша проблема может быть одинаковой или может быть другой проблемой, но убедитесь, что инспектор элементов не обманул.

Ответ 3

Я только что решил аналогичную проблему. document.createElement(и я предполагаю document.createElementNS), при вызове с HTML-страницы создается HTML node (где дело не имеет значения), а не xml node.

В Chrome работает следующее:

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

вы получите свой смешанный футляр node.

Ответ 4

приведенный ответ слишком обширен и не очень полезен для меня, и я нахожу его очень хлопотным или просто сказать фикцию. Если бы я был вами, я бы просто получил по элементу в html с тегом say:

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

и когда мне нужно создать элемент или добавить информацию, я просто сделаю:

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

Надеюсь, что это было полезно.