</head>
<body style="background-color: #c7c7ff">
-<div id="absolute"><label>Absolute: <input type="range" min="0" max="1" step="0.01"></slider></label><span></span></div>
-<div id="position"><label>Position: <input type="range" min="0" max="5" step="0.01"></slider></label><span></span></div>
+<!-- <div id="absolute"><label>Absolute: <input type="range" min="0" max="1" step="0.01"></slider></label><span></span></div>
+<div id="position"><label>Position: <input type="range" min="0" max="5" step="0.01"></slider></label><span></span></div> -->
+
+<button name="back1000">Back 1000</button>
+<button name="back100">Back 100</button>
+<button name="forth100">Forth 100</button>
+<button name="forth1000">Forth 1000</button>
+<button name="speed2">Speed x2</button>
+<button name="speed05">Speed x0.5</button>
+<button name="stop">Stop</button>
+<button name="finish">Finish</button>
+<button name="pause">Pause</button>
+<button name="play">Play</button>
+<button name="reverse">Reverse</button>
+<span id="displayText"></span>
<!-- Making the svg -->
<svg width=1000px height=1000px id="canvas" viewbox="-1000 -2000 5000 5000">
SVG.defaults.timeline.ease = '-'
var r = new SVG.Runner(1000)
-var t = new SVG.Timeline()
+var t = new SVG.Timeline().persist(true)
+
r.schedule(t, 200)
.animate(500).loop(5, true, 100)
.animate(600, 200, 'absolute')
mover.clone().insertAfter(mover)
canvas.line(100, 300, 800, 300).attr('stroke', 'black')
+const text = SVG('#displayText')
+
t.on('time', function (e) {
mover.x(100 + e.detail/10)
+ text.node.textContent = e.detail
+})
+
+t.on('finished', () => {
+ console.log('finished')
+})
+
+SVG('button[name="back100"]').on('click', () => {
+ t.seek(-100)
+})
+SVG('button[name="back1000"]').on('click', () => {
+ t.seek(-1000)
+})
+SVG('button[name="forth100"]').on('click', () => {
+ t.seek(100)
+})
+SVG('button[name="forth1000"]').on('click', () => {
+ t.seek(1000)
+})
+
+SVG('button[name="speed2"]').on('click', () => {
+ t.speed(2)
+})
+
+SVG('button[name="speed05"]').on('click', () => {
+ t.speed(0.5)
+})
+
+SVG('button[name="pause"]').on('click', () => {
+ t.pause()
+})
+
+SVG('button[name="play"]').on('click', () => {
+ t.play()
+})
+
+SVG('button[name="stop"]').on('click', () => {
+ t.stop()
+})
+
+SVG('button[name="finish"]').on('click', () => {
+ t.finish()
+})
+
+SVG('button[name="reverse"]').on('click', () => {
+ t.reverse()
})
* @copyright Wout Fierens <wout@mick-wout.com>
* @license MIT
*
-* BUILT: Wed Nov 21 2018 22:04:17 GMT+0100 (GMT+01:00)
+* BUILT: Thu Nov 22 2018 15:30:35 GMT+0100 (GMT+01:00)
*/;
var SVG = (function () {
'use strict';
return node;
},
cancelFrame: function cancelFrame(node) {
- Animator.frames.remove(node);
+ node != null && Animator.frames.remove(node);
},
clearTimeout: function clearTimeout(node) {
- Animator.timeouts.remove(node);
+ node != null && Animator.timeouts.remove(node);
},
_draw: function _draw(now) {
// Run all the timeouts we can run, if they are not ready yet, add them
_this._order = [];
_this._time = 0;
_this._lastSourceTime = 0;
- _this._lastStepTime = 0;
+ _this._lastStepTime = 0; // Make sure that step is always called in class context
+
+ _this._step = _this._step.bind(_assertThisInitialized(_assertThisInitialized(_this)));
return _this;
} // schedules a runner on the timeline
this._runners[runner.id] = {
persist: this.persist(),
runner: runner,
- start: absoluteStartTime // Save order and continue
+ start: absoluteStartTime // + delay
+ // Save order and continue
};
value: function play() {
// Now make sure we are not paused and continue the animation
this._paused = false;
+ this._lastSourceTime = this._timeSource();
return this._continue();
}
}, {
key: "pause",
value: function pause() {
- // Cancel the next animation frame and pause
- this._nextFrame = null;
this._paused = true;
- return this;
+ return this._continue();
}
}, {
key: "stop",
value: function stop() {
- // Cancel the next animation frame and go to start
+ // Go to start and pause
this.seek(-this._time);
return this.pause();
}
}, {
key: "finish",
value: function finish() {
+ // Go to Infinity and pause
this.seek(Infinity);
return this.pause();
}
}, {
key: "seek",
value: function seek(dt) {
- this._time += dt;
- return this._continue();
+ this._time += dt; // this._lastStepTime = this._time
+
+ return this._continue(true);
}
}, {
key: "time",
}, {
key: "_step",
value: function _step() {
- // If the timeline is paused, just do nothing
- if (this._paused) return; // Get the time delta from the last time and update the time
+ var immediateStep = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
+ // Get the time delta from the last time and update the time
var time = this._timeSource();
var dtSource = time - this._lastSourceTime;
+ if (immediateStep) dtSource = 0;
var dtTime = this._speed * dtSource + (this._time - this._lastStepTime);
- this._lastSourceTime = time; // Update the time
+ this._lastSourceTime = time; // Only update the time if we use the timeSource.
+ // Otherwise use the current time
+
+ if (!immediateStep) {
+ // Update the time
+ this._time += dtTime;
+ }
- this._time += dtTime;
this._lastStepTime = this._time;
this.fire('time', this._time); // Run all of the runners directly
var dtToStart = this._time - runnerInfo.start; // Dont run runner if not started yet
- if (dtToStart < 0) {
- runnersLeft = true;
+ if (dtToStart <= 0) {
+ runnersLeft = true; // This is for the case that teh timeline was seeked so that the time
+ // is now before the startTime of the runner. Thats why we need to set
+ // the runner to position 0
+
+ runner.reset();
continue;
} else if (dtToStart < dt) {
// Adjust dt to make sure that animation is on point
runner.timeline(null);
}
}
- } // Get the next animation frame to keep the simulation going
-
+ }
if (runnersLeft) {
- this._nextFrame = Animator.frame(this._step.bind(this));
+ this._continue();
} else {
this.fire('finished');
this._nextFrame = null;
}, {
key: "_continue",
value: function _continue() {
+ var immediateStep = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
+ Animator.cancelFrame(this._nextFrame);
+ this._nextFrame = null;
+ if (immediateStep) return this._step(true);
if (this._paused) return this;
-
- if (!this._nextFrame) {
- this._nextFrame = Animator.frame(this._step.bind(this));
- }
-
+ this._nextFrame = Animator.frame(this._step);
return this;
}
}, {
_this.enabled = true;
_this._time = 0;
- _this._last = 0; // Save transforms applied to this runner
+ _this._last = 0; // At creation, the runner is in reseted state
+
+ _this._reseted = true; // Save transforms applied to this runner
_this.transforms = new Matrix();
_this.transformId = 1; // Looping variables
this.done = !declarative && !justFinished && this._time >= duration; // Call initialise and the run function
if (running || declarative) {
+ // Runner is running. So its not in reseted state anymore
+ this._reseted = false;
+
this._initialise(running); // clear the transforms on this runner so they dont get added again and again
return this;
}
}, {
+ key: "reset",
+ value: function reset() {
+ if (this._reseted) return this;
+ this.loops(0);
+ this._reseted = true;
+ return this;
+ }
+ }, {
key: "finish",
value: function finish() {
return this.step(Infinity);
},
cancelFrame (node) {
- Animator.frames.remove(node)
+ node != null && Animator.frames.remove(node)
},
clearTimeout (node) {
- Animator.timeouts.remove(node)
+ node != null && Animator.timeouts.remove(node)
},
_draw (now) {
this._time = 0
this._last = 0
+ // At creation, the runner is in reseted state
+ this._reseted = true
+
// Save transforms applied to this runner
this.transforms = new Matrix()
this.transformId = 1
// Call initialise and the run function
if (running || declarative) {
+ // Runner is running. So its not in reseted state anymore
+ this._reseted = false
+
this._initialise(running)
// clear the transforms on this runner so they dont get added again and again
this.transforms = new Matrix()
var converged = this._run(declarative ? dt : position)
+
this.fire('step', this)
}
// correct the done flag here
return this
}
+ reset () {
+ if (this._reseted) return this
+ this.loops(0)
+ this._reseted = true
+ return this
+ }
+
finish () {
return this.step(Infinity)
}
this._time = 0
this._lastSourceTime = 0
this._lastStepTime = 0
+
+ // Make sure that step is always called in class context
+ this._step = this._step.bind(this)
}
// schedules a runner on the timeline
this._runners[runner.id] = {
persist: this.persist(),
runner: runner,
- start: absoluteStartTime
+ start: absoluteStartTime// + delay
}
// Save order and continue
play () {
// Now make sure we are not paused and continue the animation
this._paused = false
+ this._lastSourceTime = this._timeSource()
return this._continue()
}
pause () {
- // Cancel the next animation frame and pause
- this._nextFrame = null
this._paused = true
- return this
+ return this._continue()
}
stop () {
- // Cancel the next animation frame and go to start
+ // Go to start and pause
this.seek(-this._time)
return this.pause()
}
finish () {
+ // Go to Infinity and pause
this.seek(Infinity)
return this.pause()
}
seek (dt) {
this._time += dt
- return this._continue()
+ // this._lastStepTime = this._time
+ return this._continue(true)
}
time (time) {
return this
}
- _step () {
- // If the timeline is paused, just do nothing
- if (this._paused) return
-
+ _step (immediateStep = false) {
// Get the time delta from the last time and update the time
var time = this._timeSource()
var dtSource = time - this._lastSourceTime
+
+ if (immediateStep) dtSource = 0
+
var dtTime = this._speed * dtSource + (this._time - this._lastStepTime)
this._lastSourceTime = time
- // Update the time
- this._time += dtTime
+ // Only update the time if we use the timeSource.
+ // Otherwise use the current time
+ if (!immediateStep) {
+ // Update the time
+ this._time += dtTime
+ }
this._lastStepTime = this._time
this.fire('time', this._time)
let dtToStart = this._time - runnerInfo.start
// Dont run runner if not started yet
- if (dtToStart < 0) {
+ if (dtToStart <= 0) {
runnersLeft = true
+
+ // This is for the case that teh timeline was seeked so that the time
+ // is now before the startTime of the runner. Thats why we need to set
+ // the runner to position 0
+ runner.reset()
continue
} else if (dtToStart < dt) {
// Adjust dt to make sure that animation is on point
}
}
- // Get the next animation frame to keep the simulation going
if (runnersLeft) {
- this._nextFrame = Animator.frame(this._step.bind(this))
+ this._continue()
} else {
this.fire('finished')
this._nextFrame = null
}
+
return this
}
// Checks if we are running and continues the animation
- _continue () {
+ _continue (immediateStep = false) {
+ Animator.cancelFrame(this._nextFrame)
+ this._nextFrame = null
+
+ if (immediateStep) return this._step(true)
if (this._paused) return this
- if (!this._nextFrame) {
- this._nextFrame = Animator.frame(this._step.bind(this))
- }
+
+ this._nextFrame = Animator.frame(this._step)
return this
}