zoukankan      html  css  js  c++  java
  • 动画组件(wagang版)之基础篇:时长、进度、帧

    页面动画是一种很常见的效果,很多同学因它而对js产生兴趣,甚至jquery把它放在核心库里。
    QWrap的核心库,并没有提供动画组件。wagang版动画组件是依赖QWrap开发出的一个动画组件。它的前身是youa网站使用的animation组件,原作者是Jerry Qu,改装成wagang组件时作了一些修改。
    文档与示例参见:http://dev.qwrap.com/resource/js/wagang/anim/_examples/index.html
    anim.js是一个复合js,它由四个js组成:
    document.write('<script type="text/javascript" src="' + srcPath + 'wagang/anim/anim_base.js"></script>');
    document.write(
    '<script type="text/javascript" src="' + srcPath + 'wagang/anim/elanim.js"></script>');
    document.write(
    '<script type="text/javascript" src="' + srcPath + 'wagang/anim/easing.js"></script>');
    document.write(
    '<script type="text/javascript" src="' + srcPath + 'wagang/anim/anim_retouch.js"></script>');

    动画提供了以下四个类:
    anim_base.js产出基础动画类QW.Anim。主要是时间、帧、播放进度等的一个管理器,相当于一个万能动画。
    elanim.js产出三个针对元素的动画类:QW.ElAnim、QW.ColorAnim、QW.ScrollAnim 。
    easing.js产出算子集合:QW.Easing。
    anim_retouch.js是添加一些易于调用的动画相关方法,例如:W('#id').toggleSlide();

    先看一下基础动画类。源码大略为:
    View Code
    /*
    Copyright QWrap
    version: $version$ $release$ released
    author: JK
    */

    (
    function() {
    var CustEvent = QW.CustEvent,
    mix
    = QW.ObjectH.mix;

    /**
    * @class Anim 动画
    * @namespace QW
    * @constructor
    * @param {function} animFun - 管理动画效果的闭包
    * @param {int} dur - 动画效果持续的时间
    * @param {json} opts - 其它参数,
    ---目前只支持以下参数:
    {boolean} byStep (Optional) 是否按帧动画(即"不跳帧")。如果为true,表示每一帧都走到,帧数为dur/frameTime
    {boolean} frameTime (Optional) 帧间隔时间。默认为28
    {boolean} per (Optional) 初始播放进度
    {function} onbeforeplay (Optional) onbeforeplay事件
    {function} onplay (Optional) onplay事件
    {function} onstep (Optional) onstep事件
    {function} onpause (Optional) onpause事件
    {function} onresume (Optional) onresume事件
    {function} onstop (Optional) onstop事件
    {function} onsuspend (Optional) onsuspend事件
    {function} onreset (Optional) onreset事件
    * @returns {Anim} anim - 动画对象
    */
    var Anim = function(animFun, dur, opts) {
    mix(
    this, opts);
    mix(
    this, {
    animFun: animFun,
    //animFun,动画函数,
    dur: dur, //动画时长
    byStep: false, //是否按帧动画
    per: 0, //播放进度
    frameTime: 28, //帧间隔时间
    _status: 0 //0-未播放,1-播放中,2-播放结束,4-被暂停,8-被终止
    });
    changePer(
    this, this.per);
    CustEvent.createEvents(
    this, Anim.EVENTS);
    };

    Anim.EVENTS
    = 'beforeplay,play,step,pause,resume,stop,suspend,reset'.split(',');
    /*
    * turnOn 打开动画定时器
    * @param {Anim} anim Anim实例
    * @returns {void}
    */

    function turnOn(anim) {
    anim.step();
    if (anim.isPlaying()) {
    anim._interval
    = window.setInterval(function() {
    anim.step();
    }, anim.frameTime);
    }
    }
    /*
    * turnOff 关闭动画定时器
    * @param {Anim} anim Anim实例
    * @returns {void}
    */

    function turnOff(anim) {
    window.clearInterval(anim._interval);
    }
    /*
    * changePer 调整播放进度,进度值
    * @param {Anim} anim Anim实例
    * @param {number} per 进度值,为[0,1]区间内的数值
    * @returns {void}
    */

    function changePer(anim, per) {
    anim.per
    = per;
    anim._startDate
    = new Date() * 1 - per * anim.dur;
    if (anim.byStep) {
    anim._totalStep
    = anim.dur / anim.frameTime;
    anim._currentStep
    = per * anim._totalStep;
    }
    }

    mix(Anim.prototype, {
    /**
    * 判断是否正在播放
    * @method isPlaying
    * @returns {boolean}
    */
    isPlaying:
    function() {
    return this._status == 1;
    },
    /**
    * 从0开始播放
    * @method play
    * @returns {boolean} 是否开始顺利开始。(因为onbeforeplay有可能阻止了play)
    */
    play:
    function() {
    var me = this;
    if (me.isPlaying()) me.stop();
    changePer(me,
    0);
    if (!me.fire('beforeplay')) return false;
    me._status
    = 1;
    me.fire(
    'play');
    turnOn(me);
    return true;
    },
    /**
    * 播放一帧
    * @method step
    * @param {number} per (Optional) 进度值,为[0,1]区间内的数值
    * @returns {void}
    */
    step:
    function(per) {
    var me = this;
    if (per != null) {
    changePer(me, per);
    }
    else {
    if (me.byStep) {
    per
    = me._currentStep++ / me._totalStep;
    }
    else {
    per
    = (new Date() - me._startDate) / me.dur;
    }
    this.per = per;
    }
    if (this.per > 1) {
    this.per = 1;
    }
    me.animFun(
    this.per);
    me.fire(
    'step');
    if (this.per >= 1) {
    this.suspend();
    return;
    }
    },
    /**
    * 停止播放,并预归位到0。
    * @method stop
    * @returns {void}
    */
    stop:
    function() {
    this._status = 8;
    changePer(
    this, 0);
    turnOff(
    this);
    this.fire('stop');
    },
    /**
    * 播放到最后
    * @method suspend
    * @returns {void}
    */
    suspend:
    function() {
    changePer(
    this, 1);
    this.animFun(1);
    this._status = 2;
    turnOff(
    this);
    this.fire('suspend');
    },
    /**
    * 暂停播放
    * @method pause
    * @returns {void}
    */
    pause:
    function() {
    this._status = 4;
    turnOff(
    this);
    this.fire('pause');
    },
    /**
    * 继续播放
    * @method resume
    * @returns {void}
    */
    resume:
    function() {
    changePer(
    this, this.per);
    this._status = 1;
    this.fire('resume');
    turnOn(
    this);
    },
    /**
    * 播放到最开始
    * @method reset
    * @returns {void}
    */
    reset:
    function() {
    changePer(
    this, 0);
    this.animFun(0);
    this.fire('reset');
    }
    });
    QW.provide(
    'Anim', Anim);
    }());


    我们把动画抽象一下,它由以下几个组成部分:
        时长(dur),即动画播放的时间总长。
        进度(per),播放的进度,在区间[0,1]之内。
        帧间隔时间(frameTime),即多长时间播放一帧。
        动画函数(animFun),它是每一帧的渲染函数。定时器每隔frameTime来调用一下animFun(per)。也就是说按进度播放一帧动画。
    这四个基本参数将动画抽象成为一个js类,系统的理解就是:
    在dur时间内,每隔frameTime时间,播放一次animFun(per)。

    这个类实例可以有以下方法:
        isPlaying() 判断是否正在播放 -----returns {boolean} 
        play() 从0开始播放 ----returns {boolean} 是否开始顺利开始。(因为onbeforeplay有可能阻止了play)
        step(per) 播放一帧,参数per为[0,1]区间内的数值,为可选,表示播放到某进度
        end() 播放到最后
        pause() 暂停播放
        resume() 继续播放
        reset() 播放到最开始

    “在dur时间内,每隔frameTime时间,播放一次animFun(per)。”
    例如:一个“在3秒时间内,每0.1秒,播放function(per){document.getElementById('div1').style.height = (per * 100) +'px';}”
    对应的效果就是:在3秒时间内,将div1元素的高度从0变成100。
    代码如下:
    http://dev.qwrap.com/resource/js/wagang/anim/anim_base.js
    待续。。。。

    附:QWrap网址:http://www.qwrap.com

  • 相关阅读:
    iOS真机测试中出现dyld`dyld_fatal_error错误
    给WKWebView添加进度条(swift)
    手机号、密码正则判断
    Xcode8 上架前属性列表添加权限
    系统定位
    修改UISearchBar的背景颜色
    iOS 给NSString文字上添加横线 中间和下划线
    iOS UISearchBar 设置取消按钮,回收键盘,并修改cancel为“取消”
    iOS 支付宝第三方使用步骤
    UIImagePickerController和UIAlertController结合使用
  • 原文地址:https://www.cnblogs.com/jkisjk/p/wagang_anim_base.html
Copyright © 2011-2022 走看看