summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlrich-Matthias Schäfer <ulima.ums@googlemail.com>2018-11-22 15:56:39 +0100
committerUlrich-Matthias Schäfer <ulima.ums@googlemail.com>2018-11-22 15:56:39 +0100
commitd5c01a7848154d240f434b38d802fdb65727fd7f (patch)
treeab1984c2af5274bebcce3469f1165dc77c1237fd
parentda216c2af803c50ee4bc82ec0e954a1efc1e8a4e (diff)
downloadsvg.js-d5c01a7848154d240f434b38d802fdb65727fd7f.tar.gz
svg.js-d5c01a7848154d240f434b38d802fdb65727fd7f.zip
fix Timeline so that play, pause, stop, reverse... work correctly. Update runners accordingly
-rw-r--r--dirty.html68
-rw-r--r--dist/svg.js78
-rw-r--r--src/animation/Animator.js4
-rw-r--r--src/animation/Runner.js14
-rw-r--r--src/animation/Timeline.js54
5 files changed, 168 insertions, 50 deletions
diff --git a/dirty.html b/dirty.html
index 712c13c..9380cf5 100644
--- a/dirty.html
+++ b/dirty.html
@@ -14,8 +14,21 @@
</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">
@@ -109,7 +122,8 @@ canvas.attr('viewBox', null)
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')
@@ -135,8 +149,56 @@ var mover = canvas.line(100, 100, 100, 300).attr('stroke', 'black')
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()
})
diff --git a/dist/svg.js b/dist/svg.js
index 5407a1a..544f337 100644
--- a/dist/svg.js
+++ b/dist/svg.js
@@ -6,7 +6,7 @@
* @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';
@@ -4957,10 +4957,10 @@ var SVG = (function () {
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
@@ -5041,7 +5041,9 @@ var SVG = (function () {
_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
@@ -5098,7 +5100,8 @@ var SVG = (function () {
this._runners[runner.id] = {
persist: this.persist(),
runner: runner,
- start: absoluteStartTime // Save order and continue
+ start: absoluteStartTime // + delay
+ // Save order and continue
};
@@ -5127,26 +5130,26 @@ var SVG = (function () {
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();
}
@@ -5168,8 +5171,9 @@ var SVG = (function () {
}, {
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",
@@ -5195,16 +5199,22 @@ var SVG = (function () {
}, {
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
@@ -5219,8 +5229,12 @@ var SVG = (function () {
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
@@ -5245,11 +5259,10 @@ var SVG = (function () {
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;
@@ -5261,12 +5274,12 @@ var SVG = (function () {
}, {
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;
}
}, {
@@ -5318,7 +5331,9 @@ var SVG = (function () {
_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
@@ -5563,6 +5578,9 @@ var SVG = (function () {
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
@@ -5584,6 +5602,14 @@ var SVG = (function () {
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);
diff --git a/src/animation/Animator.js b/src/animation/Animator.js
index 9b460f5..1392daa 100644
--- a/src/animation/Animator.js
+++ b/src/animation/Animator.js
@@ -43,11 +43,11 @@ const Animator = {
},
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) {
diff --git a/src/animation/Runner.js b/src/animation/Runner.js
index 47929fd..63c95d6 100644
--- a/src/animation/Runner.js
+++ b/src/animation/Runner.js
@@ -50,6 +50,9 @@ export default class Runner extends EventTarget {
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
@@ -276,11 +279,15 @@ export default class Runner extends EventTarget {
// 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
@@ -292,6 +299,13 @@ export default class Runner extends EventTarget {
return this
}
+ reset () {
+ if (this._reseted) return this
+ this.loops(0)
+ this._reseted = true
+ return this
+ }
+
finish () {
return this.step(Infinity)
}
diff --git a/src/animation/Timeline.js b/src/animation/Timeline.js
index a0d8069..bafd319 100644
--- a/src/animation/Timeline.js
+++ b/src/animation/Timeline.js
@@ -38,6 +38,9 @@ export default class Timeline extends EventTarget {
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
@@ -92,7 +95,7 @@ export default class Timeline extends EventTarget {
this._runners[runner.id] = {
persist: this.persist(),
runner: runner,
- start: absoluteStartTime
+ start: absoluteStartTime// + delay
}
// Save order and continue
@@ -115,23 +118,23 @@ export default class Timeline extends EventTarget {
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()
}
@@ -152,7 +155,8 @@ export default class Timeline extends EventTarget {
seek (dt) {
this._time += dt
- return this._continue()
+ // this._lastStepTime = this._time
+ return this._continue(true)
}
time (time) {
@@ -173,18 +177,22 @@ export default class Timeline extends EventTarget {
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)
@@ -201,8 +209,13 @@ export default class Timeline extends EventTarget {
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
@@ -231,22 +244,25 @@ export default class Timeline extends EventTarget {
}
}
- // 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
}