13

AnimateClip

Objective
  • Responder
    • View
      • Clip
        • AnimateClip
Objective.js

Move the pointer of the mouse over the clip. Click in the clip or press the space bar to start playing it. Click or press again the space bar to pause it, continue to play it. Use the right and left arrows to move forward or backward by one second, press the Shift key or the Ctrl key at the same time to move forward or backward by ten seconds or a hundred milliseconds. Press the 0 key to come back to the beginning. Press the plus key to play the clip faster, the minus key to play it slower, the asterisk key to play it at the normal speed.

  1. function AnimateClip() {
  2.     Clip.call(this);
  3.  
  4.     this._animlist = null;
  5.     this._lastanim = null;
  6. }
  7.  
  8. AnimateClip.prototype = Object.create(Clip.prototype);
  9.  
  10. Object.defineProperty(AnimateClip.prototype, 'constructor', { value: AnimateClip, enumerable: false, writable: true });
  11.  
  12. Object.defineProperty(AnimateClip.prototype, 'currentTime', {
  13.     get:    function() {
  14.         return this._animlist ? Math.floor(this._lastanim.currentTime) : 0;
  15.     }
  16. });
  17.  
  18. Object.defineProperty(AnimateClip.prototype, 'playbackRate', {
  19.     get:    function() {
  20.         return this._playbackRate;
  21.     },
  22.     set:    function(r) {
  23.         if (typeof r !== 'number')
  24.             throw new TypeError();
  25.  
  26.         if (r < Clip.minPlaybackRate || r > Clip.maxPlaybackRate)
  27.             throw new RangeError();
  28.  
  29.         this._playbackRate = r;
  30.  
  31.         if (this._animlist)
  32.             for (let e of this._animlist)
  33.                 e.playbackRate = r;
  34.     }
  35. });
  36.  
  37. AnimateClip.prototype.animate = function(animations, autoplay = false) {
  38.     if (! (Array.isArray(animations) && animations.length > 0))
  39.         throw new TypeError();
  40.  
  41.     if (this._animlist)
  42.         for (let e of this._animlist)
  43.             e.cancel();
  44.  
  45.     let duration = 0, lastanim;
  46.  
  47.     const animlist = [];
  48.  
  49.     for (let e of animations) {
  50.         if (! (Array.isArray(e) && e.length == 3))
  51.             throw new TypeError();
  52.  
  53.         let [widget, keyframes, options] = e;
  54.  
  55.         options.playbackRate = this._playbackRate;
  56.  
  57.         let anim = widget.animate(keyframes, options);
  58.  
  59.         let ms = (options.delay || 0) + options.duration * (options.iterations || 1) + (options.endDelay || 0);
  60.  
  61.         if (ms > duration) {
  62.             lastanim = anim;
  63.             duration = ms;
  64.         }
  65.  
  66.         animlist.push(anim);
  67.     }
  68.  
  69.     lastanim.onfinish = () => {
  70.         this._ended = this._paused = true;
  71.  
  72.         this.notify('clipEnded', this);
  73.     };
  74.  
  75.     this._duration = duration;
  76.  
  77.     this._animlist = animlist;
  78.     this._lastanim = lastanim;
  79.  
  80.     if (!autoplay)
  81.         for (let e of animlist)
  82.             e.pause();
  83.  
  84.     this._paused = !autoplay;
  85.  
  86.     this._ended = false;
  87.  
  88.     return this;
  89. };
  90.  
  91. AnimateClip.prototype.seek = function(ms) {
  92.     if (!this._animlist)
  93.         return this;
  94.  
  95.     for (let e of this._animlist) {
  96.         e.currentTime = ms;
  97.         if (this._paused)
  98.             e.pause();
  99.     }
  100.  
  101.     this.notify('clipSeeked', this);
  102.  
  103.     return this;
  104. };
  105.  
  106. AnimateClip.prototype.play = function() {
  107.     if (!this._animlist)
  108.         return this;
  109.  
  110.     for (let e of this._animlist)
  111.         if (this._ended || e.playState != 'finished')
  112.             e.play();
  113.  
  114.     this._ended = this._paused = false;
  115.  
  116.     return this;
  117. };
  118.  
  119. AnimateClip.prototype.pause = function() {
  120.     if (!this._animlist)
  121.         return this;
  122.  
  123.     for (let e of this._animlist)
  124.         if (e.playState != 'finished')
  125.             e.pause();
  126.  
  127.     this._paused = true;
  128.  
  129.     return this;
  130. };
Test
  1. <?php $text='Objective.js'; ?>
  2. <?php $font='Slackey'; ?>
  3. <?php $fontSize=60; ?>
  4. <?php $color='#3bc'; ?>
  1. <?php head('font', $font); ?>
  1. <?php $id=uniqid('id'); ?>
  1. .test_display {
  2.     display: inline-block;
  3.     color: <?php echo $color; ?>;
  4.     font-family: "<?php echo $font; ?>", sans-serif;
  5.     font-size: <?php echo $fontSize; ?>px;
  6.     user-select: none;
  7. }
  8. .test_display .letter {
  9.     display: inline-block;
  10.     transform-origin: 50% 100%;
  11. }
  1. <div id="<?php echo $id; ?>" class="noprint">
  2. <div class="test_display"><div><?php echo $text; ?></div></div>
  3. </div>
  1. <?php head('javascript', '/objectivejs/Objective.js'); ?>
  2. <?php head('javascript', '/objectivejs/Responder.js'); ?>
  3. <?php head('javascript', '/objectivejs/View.js'); ?>
  4. <?php head('javascript', '/objectivejs/Clip.js'); ?>
  5. <?php head('javascript', '/objectivejs/AnimateClip.js'); ?>
  1. const container = document.querySelector('#<?php echo $id; ?>');
  2.  
  3. const display = container.querySelector('.test_display');
  4.  
  5. const wrapper = display.querySelector('div');
  6. wrapper.innerHTML = wrapper.textContent.replace(/\S/g, "<span class='letter'>$&</span>");
  7.  
  8. const clip = new AnimateClip();
  9.  
  10. clip.setWidget(display);
  1. const duration = 2000, delay = 1000;
  2.  
  3. const animations = [];
  4.  
  5. const letters = wrapper.querySelectorAll('.letter');
  6.  
  7. for (let i = 0; i < letters.length; i++) {
  8.     let keyframes = [ {transform: 'scale(0)'}, {transform: 'scale(1)'} ];
  9.     let options = {delay: delay + 50 * i, duration: duration, easing: 'ease-in-out'};
  10.  
  11.     animations.push([letters[i], keyframes, options]);
  12. }
  13.  
  14. const text_keyframes = [ {opacity: 1}, {opacity: 0} ];
  15. const text_options = {delay: delay + duration + letters.length * 50, duration: 1000, easing: 'ease-in-out'};
  16.  
  17. animations.push([wrapper, text_keyframes, text_options]);
  18.  
  19. clip.animate(animations);
  20.  
  21. clip.enablePlayer();
SEE ALSO

Clip, ProgramClip, VideoClip, Editing an animated clip

Comments

Your comment:
[p] [b] [i] [u] [s] [quote] [pre] [br] [code] [url] [email] strip help 2000

Enter a maximum of 2000 characters.
Improve the presentation of your text with the following formatting tags:
[p]paragraph[/p], [b]bold[/b], [i]italics[/i], [u]underline[/u], [s]strike[/s], [quote]citation[/quote], [pre]as is[/pre], [br]line break,
[url]http://www.izend.org[/url], [url=http://www.izend.org]site[/url], [email]izend@izend.org[/email], [email=izend@izend.org]izend[/email],
[code]command[/code], [code=language]source code in c, java, php, html, javascript, xml, css, sql, bash, dos, make, etc.[/code].