'animations with svg.js - adding runners to timelines
I wish to have animations that are controlled by buttons. My idea is to have a number of timelines which I can play() eg when the correct button is clicked.
I'm new to this library and am confused about the animation system.
[This code is deliberately verbose, and not in the svs.js coding style]
var myRect = canvas.rect(30,30);
myRect.fill('blue');
myRect.attr({x: '-15', y: '-15'});
var myRectRunner1 = myRect.animate(2000).ease('-').attr({x: '25', y: '-15'});
var myTimeline1 = new SVG.Timeline();
myTimeline1.persist(true); // otherwise runners are deleted after running
myTimeline1.schedule(myRectRunner1, 0, 'last'); // I will add other runners too
myTimeline1.time(0); // docs don't say if this is needed; be safe
This actually works, using myTimeline1.play() when the click event fires.
But what I think is happening from experiments is that as I create myRectRunner1 a new timeline is created which is immediately played; then when I add the runner to myTimeline, the old timeline is stopped or reset, and the runner becomes bound to myTimeline, and awaits the instruction to play.
Is that correct?
What's a good way to proceed?
var myRectRunner1 = myRect.animate(2000).ease('-').attr({x: '25', y: '-15'}).active(false);
and make the runner active once it has been loaded onto myTimeline?
This works, but it's a bit messy.
I could create a new runner [var runner = new SVG.Runner(2000)], add it to myTimeline, and then specify the target attr() once it is on the timeline - again a bit messy, as it separates the duration from the rest of animation spec.
But I suspect there's a good way that I haven't discovered yet.
=======
General questions:
- What happens if I reduce the duration of a runner once it is on the timeline? Does the following runner still execute immediately after (ie the timeline stores the runner sequence), or does the timeline simply store the time of execution so there will be a gap?
- I think (visually) that the default easing is '<>', if easing is not specified - is that correct?
- How do I fire an event when the timeline ends? I'm currently adding a final dummy runner of zero duration:
myDummyRunner.after(myfunction), but there might possibly be some method likemyTimeline.after(myfunction) - If I fire an event as
myTimelineends and specifymyTimeline.reverse()in the event handler, there is a delay of about a second before the animation starts to run backwards - is that delay intentional or inevitable, or is there something I don't understand? - Can I actually have more than one timeline? Can I add the same runner to different timelines, as long as I take responsibility for conflicts? In that case what does
myRect.timeline()return? (undocumented method of an element that is used as an example in the SVG.Timeline docs). Indeed what doesmyRectRunner1.timeline()return?
Thank you for any help/insights you can offer - I'm pretty sure that I don't understand this well enough, and that the answers will become obvious once I do.
Solution 1:[1]
Well, in case it helps someone else:
The library code has been written by excellent coders - the code seems beautifully structured, clean and very efficent
The documentation has been written by excellent coders - but oh dear, you need someone who is good at documentation, and will keep the docs up to date. There are two big things here:
- the docs claim that the library will work with IE9 - that is untrue; it won't work for a minimum 7% of punters according to caniuse. Presumably the code was changed but not the docs. It is bad to mislead people thus.
- if you need more than the basics, you'll have to read the code - that makes the library very expensive to use.
Trying to answer my own questions:
What happens if I reduce the duration of a runner once it is on the timeline? Does the following runner still execute immediately after (ie the timeline stores the runner sequence), or does the timeline simply store the time of execution so there will be a gap?
When a runner is scheduled onto a timeline it is given a time of execution relative to the start of the timeline. Runners are not stored in sequence - they run when their time is reached. It isn't possible to change duration - but you can unschedule the runner, and schedule it again with a new duration. You may have to access the time at it would have run and set that - if you schedule with when = 'absolute' the delay parameter now sets the time at which the runner will run, though the docs don't tell you. Another undocumented feature is when = 'with-last', which starts the runner (beginning with any delay) when the previously added runner starts to move, ie after any delay on the previous runner. That is different to when = 'last', which starts the runner at the latest point used on the timeline, rather than the end of the previously added runner.
I think (visually) that the default easing is '<>', if easing is not specified - is that correct?
No, it looks like it, but the code says '>'
How do I fire an event when the timeline ends? I'm currently adding a final dummy runner of zero duration: myDummyRunner.after(myfunction), but there might possibly be some method like myTimeline.after(myfunction)
myTimeline.on('finished', myFunction)
Timeline is rather silent - not really designed for what I wanted. I've added dummy runners copiously, because I need to know where I am on the timeline. One major snag is that even though runners can tell you when they start ('start' event) and finish ( .after() ) neither of these fire when you run the timeline backwards; I've ended up catching the 'step' event, (.during() ) in a dummy runner. Yuk.
If I fire an event as myTimeline ends and specify myTimeline.reverse() in the event handler, there is a delay of about a second before the animation starts to run backwards - is that delay intentional or inevitable, or is there something I don't understand?
This doesn't happen to me now.
Can I actually have more than one timeline? Can I add the same runner to different timelines, as long as I take responsibility for conflicts? In that case what does myRect.timeline() return? (undocumented method of an element that is used as an example in the SVG.Timeline docs). Indeed what does myRectRunner1.timeline() return?
Yes, more than one timeline. Only use a runner once, I think, but not sure. myRect.timeline() simply returns the timeline that you previously set - the timeline stored with myRect is only used when you .animate(), to specify the timeline that the runner sits on - it does nothing else to myRect, doesn't bind it to a timeline at all.
==
I hope that lot might help someone else
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | drex |
