user37886 user37886 - 24 days ago 6
Javascript Question

setTimeout not working when used for svg

I want to move a circle in a line say after 3 sec. I am using JS to dynamically draw a circle and move it and setTimeout for time delay. when i load the page the circle appears after 3 sec but in meantime has traveled some distance on the line (it was supposed to start from the beginning of the line i.e (30,y1)). I cannot figure out where i went wrong.
here are relevant codes:

train.js

function RunTrain(x,y,desti,time,r)
{
var xmlns="http://www.w3.org/2000/svg";
var C=document.createElementNS(xmlns,"circle");
C.setAttributeNS(null,"cx",x);
C.setAttributeNS(null,"cy",y);
C.setAttributeNS(null,"r",r);
C.setAttribute("style","stroke-width:1;stroke:blue;fill:skyblue");

var animate=document.createElementNS(xmlns,"animate");
animate.setAttribute("attributeName","cx");
animate.setAttribute("attributeType","XML");
animate.setAttribute("from",x);
animate.setAttribute("to",desti);
animate.setAttribute("dur","2s");
animate.setAttribute("begin","0s");
animate.setAttribute("repeatCount","1");
animate.setAttribute("fill","freeze");

C.appendChild(animate);
document.getElementById("id1").appendChild(C);
//id1 is the id of svg tag
}


call.js

setTimeout(function(){ RunTrain(30,y1,Mlx2,5,10); },3000);


demo.html

<svg height = 5000 width = 5000 id="id1"> </svg>
<script src="/static/train.js"></script>
<script src="/static/call.js"></script>


Note: it is a part of django project. I am using mozilla.


Edit

This animateTransform is also causing trouble even on calling beginElement on it.

var animateTransform=document.createElementNS(xmlns,"animateTransform");
animateTransform.setAttribute("attributeName","transform");
animateTransform.setAttribute("attributeType","scale");
animateTransform.setAttribute("dur","2s");
animateTransform.setAttribute("begin","3s");
animateTransform.setAttribute("from","0 0");
animateTransform.setAttribute("to","160 "+ y1);
animateTransform.setAttribute("fill","freeze");

Answer

The animation timer for SMIL animation begins ticki ng when the SVG document is created. So if you say begin="0s" that means the animation should start when the document is first created. In your case, that is when the <svg> is added to the DOM. Not when you add the <circle> and <animate> elements three seconds later. So the animation is begins as if you were already running for three seconds.

The simplest fix for your code is to set begin="indefinite" and start the animation running after you add the elements. You do that by calling beginElement(). See the demo below.

function RunTrain(x,y,desti,time,r)
{
    var xmlns="http://www.w3.org/2000/svg";
    var C=document.createElementNS(xmlns,"circle");
    C.setAttributeNS(null,"cx",x);
    C.setAttributeNS(null,"cy",y);
    C.setAttributeNS(null,"r",r);
    C.setAttribute("style","stroke-width:1;stroke:blue;fill:skyblue");

    var animate=document.createElementNS(xmlns,"animate");
    animate.setAttribute("attributeName","cx");
    animate.setAttribute("attributeType","XML");
    animate.setAttribute("from",x);
    animate.setAttribute("to",desti);
    animate.setAttribute("dur",time);
    animate.setAttribute("begin","indefinite");
    animate.setAttribute("repeatCount","1");
    animate.setAttribute("fill","freeze");

    C.appendChild(animate);
    document.getElementById("id1").appendChild(C);
    //id1 is the id of svg tag
  
    animate.beginElement();
}

var y1 = 30;
var Mlx2 = 400;

setTimeout(function(){ RunTrain(30,y1,Mlx2,5,10); },3000);
<svg height="5000" width="5000" id="id1"></svg>