zoukankan      html  css  js  c++  java
  • js动画框架设计

    题记: 当你不再依赖JQuery时,当你已经厌倦了引入js类库实现一些动画效果的方式,当你想实现一个简单而实用的动画框架......下面介绍下愚人设计的动画框架:支持动画缓动算法函数,如Linear、Cubic、Back、Bounce,支持改变高度,宽度,透明度,边框,外边距的基本动画,支持动画的回调函数,如开始、暂停、完成的callback等。

    Section One

    游戏动画,Flash动画里一个比较重要的概念是帧频,即每秒播放多少帧动画,一般动画是30帧/秒,单位为fps(frames per second)。

    对于匀速运动来说:如果一个动画的持续时间duration为500ms,帧频frequence为30fps,则总帧数frames为(500/1000)*30 = 15,即该动画过程有15个“画面”,每走一帧,都计算出一个画面:画面当前位置 = 开始位置 + (当前帧/总帧数)(结束位置-开始位置),如果当前帧是最后一帧,则动画结束。其中setTimeout或setInterval每隔(500/15)ms时间段调用一次函数,即计算一个画面。

    来看下线性运动Linear缓动算法函数,t表示当前帧,b表示开始位置,c表示发生偏移的距离值,即当前位置-开始位置,d表示总帧数,符合上面的推理解释,对于其他的算法函数,道理其实都是一样,只不过在运动过程中的曲线不同,有些呈现抛物线,有些呈现线性指数,对于数学感兴趣的可以研究下这些算法函数,我也是略知皮毛:

    Linear: function (t, b, c, d) {
    	return c * t / d + b;
    }
    

    清楚了以上问题后,对于js的动画框架设计,就迎刃而解了,废话不多说,来个 demo 先。

    Section Two

    代码总体结构,具体说明看注释,需注意的问题:1)在私有作用域里定义的变量,要在外部能访问到,需挂在window全局对象下,如window.Anim = Anim;2)动画元素需要设置定位position属性;3)传入的外边距参数需要驼峰式命名,并且当同时设置targetPos(元素目标位置)和外边距时,外边距的值会覆盖targetPos的值,如marginLeft的值会覆盖targetPos.left的值,因为外边距实现动画的原理也是利用元素的left、top值:

    (function(window) {
        /*
         * 工具对象
         * 包含基本的dom操作,event操作
         */
        var util = {};
        util.dom = {
            // 获取元素计算样式
            getPropValue: function(element, propName) {
            },
            // 设置透明度
            setOpacity: function(obj, num) {
                document.all ? obj.filters.alpha.opacity = num : obj.style.opacity = num / 100;
            }
            // ......
        };
        util.event = {
            // 获取事件对象
            getEvent: function(event) {
            },
            // 获取事件源目标
            getTarget: function(event) {
            },
            // 注册事件
            addEvent: function(element, event, handler) {
            },
            // 删除事件
            removeEvent: function(element, event, handler) {
            },
            // 阻止默认行为
            preventDefault: function(event) {
            },
            // 阻止事件冒泡
            stopPropagation: function(event) {
            }
            // ......
        };
    
        /*
        * 动画缓动函数
        */
        var Tween = {
            Linear: function (t, b, c, d) { return c * t / d + b; },
            Quad: {
                easeIn: function (t, b, c, d) {
                    return c * (t /= d) * t + b;
                },
                easeOut: function (t, b, c, d) {
                    return -c * (t /= d) * (t - 2) + b;
                },
                easeInOut: function (t, b, c, d) {
                    if ((t /= d / 2) < 1) return c / 2 * t * t + b;
                    return -c / 2 * ((--t) * (t - 2) - 1) + b;
                }
            },
            // ...
        };
    
        /*
         * 核心动画
         * @elem 要执行动画的元素
         * @options left、top、opacity、width、height、border、marginLeft、marginRight、marginTop、marginBottom
         */
        function Anim(elem, options) {
            this.elem = elem;
            this.options = options;
            // 默认样式属性
            this.defaults = {
            };
        }
        Anim.prototype = {
            constructor: Anim,
            // 初始化动画
            init: function() {
                this.isStart = false;
                this.isStop = false;
                this.isComplete = false;
                this.isBack = false;
                this.start();
            },
            // 初始化数据
            before: function() {
            },
            // 开始动画
            start: function() {
            },
            // 动画过程
            run: function() {
                this.before();
                // 动画参数匹配
                this.match();
                // 原路返回
                if (this.isBack) {
                    // ...
                }
                if (this.isStart) {
                    this.onStart.call(this.elem);
                    // 计算动画
                    this.count();
                }
            },
            // 匹配动画的参数
            match: function() {
            },
            // 计算动画
            count: function() {
            },
            // 原路返回
            back: function() {
            },
            // 停止动画
            stop: function() {
            },
            // 重置元素
            reset: function() {
            }
        };
    
        // 全局使用
        if (!window.util) {
            window.util = util;
        }
        if (!window.Anim) {
            window.Anim = Anim;
        }
        if (!window.Tween) {
            window.Tween = Tween;
        }
    
    })(window);
    View Code

    Last

    使用非常简单,初始化参数对象,然后调用构造函数Anim即可:

    // 动画参数设置
    var options = {
        duration: 2000, // 动画持续时间
        frequence: 30, // 帧频
        tweenFunc: Tween.Linear, // 动画缓动函数
        targetPos: {left: 400, top: 300}, // 元素目标位置
        opacity: 40, // 透明度(可选)
         80, // 宽度(可选)
        height: 80, // 高度(可选)
        // marginTop: 100, // 上边距(可选)
        border: '2px solid red', // 边框(可选)
        // 动画开始callback(可选)
        onStart: function() {
            // this指向当前动画元素
        },
        // 动画停止callback(可选)
        onStop: function() {
            // this指向当前动画元素
        },
        // 动画完成callback(可选)
        onComplete: function() {
            // this指向当前动画元素
        }
    };
    var anim = new Anim(animElem, options);

    最后附上 源代码 以及easing算法函数的 demo

    认真对待每一个人,每一件事,会有意想不到的收获!

  • 相关阅读:
    Android Media Playback 中的MediaPlayer的用法及注意事项(二)
    Android Media Playback 中的MediaPlayer的用法及注意事项(一)
    34. Search for a Range
    33. Search in Rotated Sorted Array
    32. Longest Valid Parentheses
    31. Next Permutation下一个排列
    30. Substring with Concatenation of All Words找出串联所有词的子串
    29. Divide Two Integers
    28. Implement strStr()子串匹配
    27. Remove Element
  • 原文地址:https://www.cnblogs.com/cyStyle/p/4211783.html
Copyright © 2011-2022 走看看