0

I am trying to create a SVG element using javascript, but cannot understand why it is unable to render. Here is what I did to render a single circle animation using javascript.

const svg = document.createElement("svg");
svg.setAttribute("width",120);
svg.setAttribute("height",30);
svg.setAttributeNS(null,"viewBox","0 0 120 30");
svg.setAttribute("xmlns","http://www.w3.org/2000/svg");
svg.setAttribute("fill","#f58c87");

const circleLeft = document.createElement("circle");
circleLeft.setAttribute("cx", "15");
circleLeft.setAttribute("cy", "15");
circleLeft.setAttribute("r", "15");

const animateOneLeft = document.createElement("animate");
animateOneLeft.setAttributeNS(null,"attributeName","r");
animateOneLeft.setAttribute("from",15);
animateOneLeft.setAttribute("to",15);
animateOneLeft.setAttribute("begin","0s");
animateOneLeft.setAttribute("dur","0.8s");
animateOneLeft.setAttribute("values", "15;9;15");
animateOneLeft.setAttributeNS(null,"calcMode","linear");
animateOneLeft.setAttributeNS(null,"repeatCount","indefinite");
circleLeft.append(animateOneLeft);

const animateTwoLeft = document.createElement("animate");
animateTwoLeft.setAttributeNS(null,"attributeName","fill-opacity");
animateTwoLeft.setAttribute("from","1");
animateTwoLeft.setAttribute("to","1");
animateTwoLeft.setAttribute("begin","0s");
animateTwoLeft.setAttribute("dur","0.8s");
animateTwoLeft.setAttribute("values","1;.5;1");
animateTwoLeft.setAttributeNS(null,"calcMode","linear");
animateTwoLeft.setAttributeNS(null,"repeatCount","indefinite");
circleLeft.append(animateTwoLeft);

svg.append(circleLeft);
document.body.append(svg);

If I write the same thing with HTML it works absolutely fine as shown below:

<svg width="120" height="30" viewBox="0 0 120 30" xmlns="http://www.w3.org/2000/svg" fill="#f58c87">
    <circle cx="15" cy="15" r="15">
        <animate attributeName="r" from="15" to="15"
                 begin="0s" dur="0.8s"
                 values="15;9;15" calcMode="linear"
                 repeatCount="indefinite" />
        <animate attributeName="fill-opacity" from="1" to="1"
                 begin="0s" dur="0.8s"
                 values="1;.5;1" calcMode="linear"
                 repeatCount="indefinite" />
    </circle>
</svg>

What is it that I am doing incorrectly with Javascript?

Suhail Gupta
  • 22,386
  • 64
  • 200
  • 328
  • Try adding the magical `document.body.innerHTML = document.body.innerHTML;` as the last line in the script? – Ollin Boer Bohan Dec 19 '19 at 04:29
  • @OllinBoerBohan Yes, adding this statement makes it work. Could you explain what just happened? – Suhail Gupta Dec 19 '19 at 04:31
  • It forces the browser to parse the SVG (by converting to text and back to DOM representation). I don't know why the browser doesn't do that automatically, but this workaround (or equivalent ones, like `document.body.innerHTML += "";`) is the only fix I've found. – Ollin Boer Bohan Dec 19 '19 at 04:35
  • @SuhailGupta, that seems like a ton of code to just render a simple circle to the DOM. Once you created the circle element in your HTML, on the JavaScript side all you needed was `const circle = document.querySelector('circle');`. Where it seems to have fallen apart is everything you did after that. Always set a baseline and go from there. – Daniel Dec 26 '19 at 17:06

0 Answers0