フレームアニメーションプラグイン

40340 ワード

アニメーションプラグインパッケージ
最近ずっとアニメーションの方法についての知识を研究して、正直に言うと确かに容易ではありませんて、主にやはりアニメーションのアルゴリズムのこの方面は比较的に难しくて、结局学んだことがありません.もちろん収穫もあって、基本的なアニメーションの原理が何なのかを理解して、だから自分も1つの簡単なアニメーションのプラグインをカプセル化して自分の学んだことを強固にしました.
アニメーションプラグインの実装方法
フロントエンドにとって、主にアニメーションを実現する方法はcss(transition,animation)、js(settimout,setInterval,requestAnimationFrame)、canvas,svgなどですが、ここでは主にrequestAnimationFrameによってアニメーション効果を実現しています.
プラグインの説明
このプラグインは5つのパラメータを受け入れます.
  • の最初のパラメータは、アニメーションが必要なターゲット要素です.
  • の2番目のパラメータは、アニメーションが必要なプロパティであり、オブジェクトです.
  • の3番目のパラメータは、アニメーションの合計時間です.
  • の4番目のパラメータはアニメーションの効果です.現在、3つのアニメーション効果、linear、easeIn、easeOutがサポートされています.
  • の5番目のパラメータは、アニメーション終了後のコールバック関数です.

  • このプラグインでは、複数のアトリビュートをアニメートしたり、単一のアトリビュートアニメーション効果を実装したり、1つのアトリビュートから1つのアトリビュートアニメーション効果を実装したりできます.コールバック関数を使用しているため、アニメーション効果を達成するために次から次へとアトリビュートが適用されると、コールバック関数のネストが発生します.
    プラグインコード
           
          
          
          
    function (element , props , duration , easing , callback) {
    if ( typeof element !== 'object' && element.nodeType !== 1) {
    return;
    };
    if ( typeof props !== 'object' && props.toString() !== '[object Object]') {
    return;
    };
    var noop = function () {};
    this.element = element;
    this.props = props;
    this.duration = duration || 600;
    this.easing = easing || 'linear';
    this.callback = callback || noop;
    this.tickID = 0;
    this.styles = this.getStyle();
    this.animate();
    };
    Animator.prototype = {
    getStyle : function () {
    return window.getComputedStyle ? window.getComputedStyle( this.element) : this.element.currentStyle();
    },
    animate : function () {
    for ( var prop in this.props) {
    this.step.call( this , prop);
    }
    },
    step : function (prop) {
    var self = this;
    var initialValue = 0;
    var beginTime = new Date();
    var endValue = parseFloat( this.props[prop]);
    var beginValue = parseFloat( this.styles[prop]);
    var changeValue = parseFloat(endValue - beginValue);
    var distance = 0;
    var move = function () {
    var p = ( new Date() - beginTime) / self.duration;
    if (p > 1) {
    self.element.style[prop] = (prop === 'opacity') ? endValue : endValue + 'px';
    cancelAnimationFrame(self.tickID);
    self.tickID = null;
    self.callback.call(self);
    } else {
    if (self.easing === 'linear') {
    distance = changeValue * p;
    } else if (self.easing === 'easeIn') {
    distance = changeValue * p * p;
    } else if (self.easing === 'easeOut') {
    distance = changeValue * ( 2 * p - p * p);
    };
    self.element.style[prop] = (prop === 'opacity') ? (beginValue + distance) : (beginValue + distance + 'px');
    this.tickID = requestAnimationFrame(move);
    }
    };
    move();
    }
    };

    インスタンスコード
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Document title>
    <style>
    *{
    margin: 0;
    padding: 0;
    list-style: none;
    }
    .box{
    width: 100px;
    height: 100px;
    background: #f60;
    position:absolute;
    top: 50;
    left: 0;
    border: 1px solid #000;   iv>
    }
    style>
    head>
    <body>
    <button id="btn">click button>
    <div id="box" class="box"> div>
    <script>
    function (element , props , duration , easing , callback) {
    if ( typeof element !== 'object' && element.nodeType !== 1) {
    return;
    };
    if ( typeof props !== 'object' && props.toString() !== '[object Object]') {
    return;
    };
    var noop = function () {};
    this.element = element;
    this.props = props;
    this.duration = duration || 600;
    this.easing = easing || 'linear';
    this.callback = callback || noop;
    this.tickID = 0;
    this.styles = this.getStyle();
    this.animate();
    };
    Animator.prototype = {
    getStyle : function () {
    return window.getComputedStyle ? window.getComputedStyle( this.element) : this.element.currentStyle();
    },
    animate : function () {
    for ( var prop in this.props) {
    this.step.call( this , prop);
    }
    },
    step : function (prop) {
    var self = this;
    var initialValue = 0;
    var beginTime = new Date();
    var endValue = parseFloat( this.props[prop]);
    var beginValue = parseFloat( this.styles[prop]);
    var changeValue = parseFloat(endValue - beginValue);
    var distance = 0;
    var move = function () {
    var p = ( new Date() - beginTime) / self.duration;
    if (p > 1) {
    self.element.style[prop] = (prop === 'opacity') ? endValue : endValue + 'px';
    cancelAnimationFrame(self.tickID);
    self.tickID = null;
    self.callback.call(self);
    } else {
    if (self.easing === 'linear') {
    distance = changeValue * p;
    } else if (self.easing === 'easeIn') {
    distance = changeValue * p * p;
    } else if (self.easing === 'easeOut') {
    distance = changeValue * ( 2 * p - p * p);
    };
    self.element.style[prop] = (prop === 'opacity') ? (beginValue + distance) : (beginValue + distance + 'px');
    this.tickID = requestAnimationFrame(move);
    }
    };
    move();
    }
    };
    var box = document.querySelector( '#box');
    var btn = document.querySelector( '#btn');
    btn.addEventListener( 'click' , function () {
    new Animator(box , {
    width : 300,
    height : 300,
    top : 200,
    left : 100,
    opacity : 0.5,
    borderWidth : 20
    });
    });
    //
    btn.addEventListener( 'click' , function () {
    new Animator(box , {
    width : 500
    } , 1000 , 'easeOut' , function () {
    new Animator(box , {
    height : 300,
    left : 100,
    borderWidth : 50
    } , 1000 , 'easeIn' , function () {
    new Animator(box , {
    opacity : 0.6
    })
    });
    });
    });
    script>