Reputation: 91
Draw(one time) and move objects every five seconds as shown in figures left to right. I searched but not able to find a way to draw outer lines and move objects near to it.
<animate xlink:href="#blue-rectangle"
attributeName="x"
from="50"
to="425"
dur="5s"
begin="circ-anim.repeat(2)"
fill="freeze"
id="rect-anim" />
ref : https://css-tricks.com/guide-svg-animations-smil/
https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Basic_Shapes
https://developer.mozilla.org/en-US/docs/Web/SVG/Element/animateMotion
Upvotes: 1
Views: 1181
Reputation: 33044
Using animateMotion
would be a solution for a continuous motion on the path. If you need to stop the movement at intervals I would use javascript. In this book: Using SVG with CSS3 and HTML5: Vector Graphics for Web Design you have a thorough description of how to use javascript to emulate animateMotion
In order to stop the rect I'n using the timestamp for the requestAnimationFrame's callback. In the next example I'm stopping the rect every 2 seconds for 1 second.
Since the timestamp is running continuously I need a way to record the moment when it stops so that I can resume the animation from here. For this I'm setting lastTime
as the last time when the rect has stopped.
Please read the comments in my code.
let rid;//the request animation frame id
let track = document.getElementById("track"),
trackLength = track.getTotalLength(),//the total length of the track
dur = 15000; //duration of one loop of track, in ms
let lastTime = 0;//last time when the rect has stopped
let flag = false;
let interval = 5000;
function update(time) {
rid = requestAnimationFrame(update);
// to stop the rect every 5 seconds
var deltaT = time%interval;
//during 1 second
if (deltaT < interval/2){
flag = false;
var t = ((deltaT + lastTime) % dur) / dur, // position in repeat cycle
distance, // distance along the path for this rect
point, // SVGPoint for that distance
point2; // SVGPoint for a slightly different distance
distance = trackLength * (t % 1);
point = track.getPointAtLength(distance);
point2 = track.getPointAtLength((distance + 2) % trackLength);
angle = Math.atan2(point.y - point2.y, point.x - point2.x);
rect.setAttribute(
"transform",
"translate(" +
[point.x, point.y] +
")" +
"rotate(" +
angle * 180 / Math.PI +
")"
);
}else{if(flag==false){lastTime += interval/2; flag = true;}}
}
rid = requestAnimationFrame(update);
svg{border:1px solid;}
path{fill:none; stroke:black;}
<svg viewBox = "0 0 150 200" width="200">
<path id="track" d="M70,30 Q70,20 80,20L120,20 Q130,20 130,30L130,170.000 Q130,180 120,180L30,180 Q20,180 20,170L20,130 Q20,120 30,120L60,120 Q70,120 70,110Z" />
<polygon id="rect" points="0,0 -10,0 -10,-10 0,-10 0,0" style="fill: #ff0000;"/>
</svg>
And this is how I would do it using animateMotion
setInterval(()=>{ svg.pauseAnimations();
setTimeout(()=>{svg.unpauseAnimations()},1000)
},2000);
svg{border:1px solid;}
path{fill:none; stroke:black;}
<svg id="svg" viewBox = "0 0 150 200" width="300">
<path id="track" d="M70,30 Q70,20 80,20L120,20 Q130,20 130,30L130,170.000 Q130,180 120,180L30,180 Q20,180 20,170L20,130 Q20,120 30,120L60,120 Q70,120 70,110Z" />
<polygon id="rect" points="0,0 10,0 10,10 0,10 0,0" style="fill: #ff0000;">
<animateMotion id="test" begin= "0s" dur="15s" repeatCount="infinite" rotate="auto" fill="freeze">
<mpath xlink:href= "#track" />
</animateMotion></polygon>
</svg>
Here is how you move 5 blocks on the path: The only difference is the begin
attribute for the animateMotion
.
all the
setInterval(()=>{ svg.pauseAnimations();
setTimeout(()=>{svg.unpauseAnimations()},1500)
},3000);
svg{border:1px solid;}
path{fill:none; stroke:black;}
<svg id="svg" viewBox = "30 0 360 450" width="300">
<defs>
<polygon id="theRect" points="0,0 20,0 20,20 0,20 0,0" style="fill: #ff0000;" />
</defs>
<path id="track" d="M288.938,33 Q289,12 310,12L350,12 Q371,12 371,33L371,408 Q371,429 350,429L66,429 Q45,429 45,408L45,374 Q45,353 66,353L267,353 Q288,353 288.062,332Z" />
<use xlink:href="#theRect">
<animateMotion id="test" begin= "0s" dur="15s" repeatCount="infinite" rotate="auto" fill="freeze" >
<mpath xlink:href= "#track" />
</animateMotion></use>
<use xlink:href="#theRect">
<animateMotion id="test" begin= "-.5s" dur="15s" repeatCount="infinite" rotate="auto" fill="freeze" >
<mpath xlink:href= "#track" />
</animateMotion></use>
<use xlink:href="#theRect">
<animateMotion id="test" begin= "-1s" dur="15s" repeatCount="infinite" rotate="auto" fill="freeze" >
<mpath xlink:href= "#track" />
</animateMotion></use>
<use xlink:href="#theRect">
<animateMotion id="test" begin= "-1.5s" dur="15s" repeatCount="infinite" rotate="auto" fill="freeze" >
<mpath xlink:href= "#track" />
</animateMotion></use>
<use xlink:href="#theRect">
<animateMotion id="test" begin= "-2s" dur="15s" repeatCount="infinite" rotate="auto" fill="freeze" >
<mpath xlink:href= "#track" />
</animateMotion></use>
</svg>
Upvotes: 3