]> source.dussan.org Git - svg.js.git/commitdiff
fix Timeline so that play, pause, stop, reverse... work correctly. Update runners...
authorUlrich-Matthias Schäfer <ulima.ums@googlemail.com>
Thu, 22 Nov 2018 14:56:39 +0000 (15:56 +0100)
committerUlrich-Matthias Schäfer <ulima.ums@googlemail.com>
Thu, 22 Nov 2018 14:56:39 +0000 (15:56 +0100)
dirty.html
dist/svg.js
src/animation/Animator.js
src/animation/Runner.js
src/animation/Timeline.js

index 712c13c140b3302c20cd8cacd6c8a147f52b1454..9380cf59157dfc03823b6ae8a524c8d28bd922e2 100644 (file)
 </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()
 })
 
 
index 5407a1ae0d6bfc39bb6fa2ecb0364f762a4dbf58..544f337a560c27d97f135124a4f4eb9d7c4ec152 100644 (file)
@@ -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);
index 9b460f56f85d85e515f324f588ed7229e22f9141..1392daaf01c93447762dab2928f661014f5d0a69 100644 (file)
@@ -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) {
index 47929fdba68a5a51b94b1c1f711aa0ef9be801ca..63c95d6159cfd4e11da1b007075da012b6be0474 100644 (file)
@@ -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)
   }
index a0d8069ebd90e21970c6fc0c066c8b8b470b9076..bafd319a4377ce4cf5d3b2c79914beeff981da6a 100644 (file)
@@ -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
   }