当你不再依赖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. js框架设计1.1命名空间笔记

    借到了司徒正美的写的js框架设计一书,司徒大神所著有些看不太懂,果然尚需循序渐进,稳扎js基础之中. 第一张开篇司徒阐述了种子模块的概念 种子模块亦为核心模块,框架最先执行模块,司徒见解应包含:对象扩 ...

  2. JS读书心得:《JavaScript框架设计》——第12章 异步处理

    一.何为异步   执行任务的过程可以被分为发起和执行两个部分. 同步执行模式:任务发起后必须等待直到任务执行完成并返回结果后,才会执行下一个任务. 异步执行模式:任务发起后不等待任务执行完成,而是马上 ...

  3. js架构设计模式——前端MVVM框架设计及实现(二)

    前端MVVM框架设计及实现(二) 在前端MVVM框架设计及实现(一)中有一个博友提出一个看法: “html中使用mvvm徒增开发成本” 我想这位朋友要表达的意思应该是HTML定义了大量的语法标记,HT ...

  4. js架构设计模式——前端MVVM框架设计及实现(一)

    前端MVVM框架设计及实现(一) 最近抽出点时间想弄个dom模块化的模板引擎,不过现在这种都是MVVM自带的,索性就想自己造轮子写一个简单的MVVM框架了 借鉴的自然还是从正美的avalon开始了,我 ...

  5. JS封装动画框架,网易轮播图,旋转轮播图

    JS封装动画框架,网易轮播图,旋转轮播图 1. JS封装运动框架 // 多个属性运动框架 添加回调函数 function animate(obj,json,fn) { clearInterval(ob ...

  6. JS框架设计之命名空间设计一种子模块

    命名空间 1.种子模块作为一个框架的最开始,除了负责初始化框架的最基础部分. 2.种子模块作为框架的最开始,那么什么是种子框架的最开始呢?答案是IIFE(立即调用函数表达式); IIFE(立即调用函数 ...

  7. JavaScript 框架设计

    JavaScript 高级框架设计 在现在,jQuery等框架已经非常完美,以致于常常忽略了JavaScript原生开发,但是这是非常重要的. 所以,我打算写一个简单的框架,两个目的 熟练框架的思想 ...

  8. 偶的《javascript框架设计》终于出版

    #cnblogs_post_body p{ text-indent:2em!important; } 历时两年多,我的书终于付梓出版了.应各方面的要求,写软文一篇,隆重介绍一下此书对各位程序员的钱途有 ...

  9. Mithril – 构建杰出 Web 应用的 JS MVC 框架

    Mithril 是一个客户端的 Javascript MVC 框架.它是一个工具,使应用程序代码分为数据层,UI 层和粘合层.提供了一个模板引擎与一个虚拟的 DOM diff 实现,用于高性能渲染,支 ...

随机推荐

  1. lua简化cocos2dx的Action动画序列

    情景 今天写代码时,又要写一个很常见的动画,就是变大变小模拟那个弹性的赶脚,很常用但写起来挺麻烦,封装一下用起来就简单多了. 当然我也知道有缓动动画(EaseAction)可以实现反弹效果,但这不是重 ...

  2. CMake入门指南-编译教程

    CMake是一个比make更高级的编译配置工具,它可以根据不同平台.不同的编译器,生成相应的Makefile或者vcproj项目.通过编写CMakeLists.txt,可以控制生成的Makefile, ...

  3. Socket网络通讯开发总结之:Java 与 C进行Socket通讯 + [备忘] Java和C之间的通讯

    Socket网络通讯开发总结之:Java 与 C进行Socket通讯 http://blog.sina.com.cn/s/blog_55934df80100i55l.html (2010-04-08 ...

  4. HDU 4643 GSM 算术几何

    当火车处在换基站的临界点时,它到某两基站的距离相等.因此换基站的位置一定在某两个基站的中垂线上, 我们预处理出任意两基站之间的中垂线,对于每次询问,求询问线段与所有中垂线的交点. 检验这些交点是否满足 ...

  5. ajax返回JSON时的处理方式

    JSON中对象通过“{}”来标识,一个“{}”代表一个对象,如{“AreaId”:”123”},对象的值是键值对的形式(key:value). json_encode() 该函数主要用来将数组和对象, ...

  6. 17.allegro导入导出[原创]

    一.从一张现成的PCB中导出元件封装到库中 --- -- 二. ①规则 ②元件摆放位置信息导出 这个时候我们在新建的电路板上: ① 导入记事文档 -- -- 到如后: 系统本来默认的是双层,这个时候变 ...

  7. Android Socket 聊天室示例

    服务端: package com.test.chatServer; import java.io.IOException; import java.net.ServerSocket; import j ...

  8. 用Eclipse+ADT创建可运行项目,创建lib项目,引用一个lib项目

    Managing Projects from Eclipse with ADT In this document Creating an Android Project  创建可运行项目 Settin ...

  9. What is the difference between DAO and DAL?

    What is the difference between DAO and DAL? The Data Access Layer (DAL) is the layer of a system tha ...

  10. 总结Selenium自动化测试方法(三)WebDriver定位元素方法

    三.WebDriver定位元素 推荐使用的webdriver是firefox,因为他的firebug更能可以帮助定位页面元素使用 # create a new Firefox session cls. ...