当你不再依赖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);
 
Last
使用非常简单,初始化参数对象,然后调用构造函数Anim即可:
 
// 动画参数设置
var options = {
    duration: 2000, // 动画持续时间
    frequence: 30, // 帧频
    tweenFunc: Tween.Linear, // 动画缓动函数
    targetPos: {left: 400, top: 300}, // 元素目标位置
    opacity: 40, // 透明度(可选)
    width: 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。
 
 
												
												
								- js框架设计1.1命名空间笔记
		
借到了司徒正美的写的js框架设计一书,司徒大神所著有些看不太懂,果然尚需循序渐进,稳扎js基础之中. 第一张开篇司徒阐述了种子模块的概念 种子模块亦为核心模块,框架最先执行模块,司徒见解应包含:对象扩 ...
		 
						- JS读书心得:《JavaScript框架设计》——第12章 异步处理
		
一.何为异步   执行任务的过程可以被分为发起和执行两个部分. 同步执行模式:任务发起后必须等待直到任务执行完成并返回结果后,才会执行下一个任务. 异步执行模式:任务发起后不等待任务执行完成,而是马上 ...
		 
						- js架构设计模式——前端MVVM框架设计及实现(二)
		
前端MVVM框架设计及实现(二) 在前端MVVM框架设计及实现(一)中有一个博友提出一个看法: “html中使用mvvm徒增开发成本” 我想这位朋友要表达的意思应该是HTML定义了大量的语法标记,HT ...
		 
						- js架构设计模式——前端MVVM框架设计及实现(一)
		
前端MVVM框架设计及实现(一) 最近抽出点时间想弄个dom模块化的模板引擎,不过现在这种都是MVVM自带的,索性就想自己造轮子写一个简单的MVVM框架了 借鉴的自然还是从正美的avalon开始了,我 ...
		 
						- JS封装动画框架,网易轮播图,旋转轮播图
		
JS封装动画框架,网易轮播图,旋转轮播图 1. JS封装运动框架 // 多个属性运动框架 添加回调函数 function animate(obj,json,fn) { clearInterval(ob ...
		 
						- JS框架设计之命名空间设计一种子模块
		
命名空间 1.种子模块作为一个框架的最开始,除了负责初始化框架的最基础部分. 2.种子模块作为框架的最开始,那么什么是种子框架的最开始呢?答案是IIFE(立即调用函数表达式); IIFE(立即调用函数 ...
		 
						- JavaScript 框架设计
		
JavaScript 高级框架设计 在现在,jQuery等框架已经非常完美,以致于常常忽略了JavaScript原生开发,但是这是非常重要的. 所以,我打算写一个简单的框架,两个目的 熟练框架的思想  ...
		 
						- 偶的《javascript框架设计》终于出版
		
#cnblogs_post_body p{ text-indent:2em!important; } 历时两年多,我的书终于付梓出版了.应各方面的要求,写软文一篇,隆重介绍一下此书对各位程序员的钱途有 ...
		 
						- Mithril – 构建杰出 Web 应用的 JS MVC 框架
		
Mithril 是一个客户端的 Javascript MVC 框架.它是一个工具,使应用程序代码分为数据层,UI 层和粘合层.提供了一个模板引擎与一个虚拟的 DOM diff 实现,用于高性能渲染,支 ...
		 
		
	
随机推荐
	
									- DWR与AJAX
			
DWR与AJAX的微妙关系 2015-08-14 10:20 447人阅读 评论(0) 收藏 举报 本文章已收录于:   // ' + obj.name + "  "; html  ...
			 
						- linux中/etc/init.d [转]
			
一.关于/etc/init.d 如果你使用过linux系统,那么你一定听说过init.d目录.这个目录到底是干嘛的呢?它归根结底只做了一件事情,但这件事情非同小可,是为整个系统做的,因此它非常重要.i ...
			 
						- 防止SQL注入和XSS攻击Filter
			
nbsp;今天系统使用IBM的安全漏洞扫描工具扫描出一堆漏洞,下面的filter主要是解决防止SQL注入和XSS攻击 一个是Filter负责将请求的request包装一下. 一个是request包装器 ...
			 
						- BZOJ 2752 高速公路(road)(线段树)
			
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2752 题意:给出一个数列A,维护两种操作: (1)将区间[L,R]之内的所有数字增加de ...
			 
						- STL笔记(1)map
			
STL笔记(1)map STL之map ZZ from http://hi.baidu.com/liyanyang/blog/item/d5c87e1eb3ba06f41bd576cf.html 1. ...
			 
						- Linux Kernel CMPXCHG函数分析
			
原文地址:http://blog.csdn.net/penngrove/article/details/44175387 最近看到Linux Kernel cmpxchg的代码,对实现很不理解.上网查 ...
			 
						- Spring的注解方式
			
在Java代码中可以使用@Resource或者@Autowired注解方式来经行注入.虽然@Resource和@Autowired都可以来完成注入依赖,但它们之间是有区别的. a.@Resource默 ...
			 
						- LA 3905 Meteor
			
给出一些点的初始位置(x, y)及速度(a, b)和一个矩形框,求能同时出现在矩形框内部的点数的最大值. 把每个点进出矩形的时刻分别看做一个事件,则每个点可能对应两个事件,进入事件和离开事件. 按这些 ...
			 
						- linux中备份mysql数据库的一个shell脚本
			
#!/bin/bash #FileName:select_into_bak.sh #Desc:Use select into outfile to backup db or tables #Creat ...
			 
						- Spark RDD操作(1)
			
https://www.zybuluo.com/jewes/note/35032 RDD是什么? RDD是Spark中的抽象数据结构类型,任何数据在Spark中都被表示为RDD.从编程的角度来看,RD ...