最近做一个广告项目,里面涉及很多动画效果,由于不能使用jquery,所以只能构建自己的动画方法。

数据结构:

elem是DOM对象,给它设置一个属性对象,用来记录elem的动画对象,比如'left','opacity'等。该对象的属性又有自己的动画队列,队列的每一项是一个对象,该对象有两个属性start,end,分别用来存储开始的值和动画结束的值,该对象有三个方法,begin,finish是开始结束动画,callbak用来保存该动画结束时需要执行的函数,见下图:

animation方法:

分词器,用来解析value表达式,比如:"+=300px"

function expr(key,value){
var r=/^(?:(\+|-)=)?(-?\d+(?:\.\d+)?)(px|)$/;
var matches=r.exec(value);
if(!matches){
throw new Error("传入参数不能运行动画");
}else{
return {
"operator":matches[1]?matches[1]:"",
"num":matches[2]?matches[2]:"",
"unit":matches[3]?matches[3]:""
};
}
}

调用上边这个方法:

var matchesEnd=expr(key,value);

就得到一个分词结果对象:

{
"operator":"+",
"num":300,
"unit":"px"
} begin方法中,我们需要先获取动画前的样式,代码如下:
var curValue=_.getAppliedStyle(elem,key);//获取当前样式
if((curValue==="auto")&&(revise[key]===0)){////修正top right bottom left width height 默认值为auto的情况
value=0;
}
temp.start=curValue;
var matchesStart=expr(key,curValue);//设置动画初始值

代码:

动画模块:

(function(window){
function expr(key,value){
var r=/^(?:(\+|-)=)?(-?\d+(?:\.\d+)?)(px|)$/;
var matches=r.exec(value);
if(!matches){
throw new Error("传入参数不能运行动画");
}else{
return {
"operator":matches[1]?matches[1]:"",
"num":matches[2]?matches[2]:"",
"unit":matches[3]?matches[3]:""
};
}
}
//method of animation
//@elem
//@properties example:{"left":"1000px",top:"200px"} opacity请使用w3c标准:0-1
//@options example:{speed:200}
function animation(elem,properties,options,callback){
var speed=options.speed||1000;
var inter=20;
if(navigator.userAgent.indexOf("MSIE 8.0")>0){
inter=80;
}
if(!elem.ani){
elem.ani={};
}
_.each(properties,function(value,key){
if(!elem.ani[key]){
elem.ani[key]=[];
}
var matchesEnd=expr(key,value);
var temp={};
if(!matchesEnd.operator){
temp.end=value;
}
var st;
if(matchesEnd.num){
var i=0;
temp.callback=callback;
temp.begin=function(){
var curValue=_.getAppliedStyle(elem,key);
temp.start=curValue;
var matchesStart=expr(key,curValue);
if(matchesEnd.operator){
temp.end=matchesStart.num*1+(matchesEnd.operator==="+"?1*matchesEnd.num:(-1)*matchesEnd.num)+matchesEnd.unit;
matchesEnd=expr(key,temp.end);
}
var gap=matchesEnd.num-matchesStart.num;
var step=gap/speed*inter;
var num=gap/step;
st=setInterval(function(){
i++;
var tempValue=matchesStart.num*1+step*i+matchesEnd.unit;
_.setStyle(elem,key,tempValue);
if(i>=num){
//修正可能的计算错误
_.setStyle(elem,key,temp.end);
if(callback){
temp.callback.call(temp);
}
clearInterval(st);
elem.ani[key].shift();
if(elem.ani[key].length){
elem.ani[key][0].begin();
}
}
},inter);
};
temp.finish=function(){
if(st){
clearInterval(st);
}
} if(elem.ani[key].push(temp)===1){
temp.begin();
}
}
},this);
}
function stop(elem,callback){
for(var key in elem.ani){
var len=elem.ani[key].length;
if(len){
elem.ani[key][0].finish();
if(elem.ani[key][0].callback){
elem.ani[key][0].callback.call(this);
}
_.setStyle(elem,key,elem.ani[key][len-1].end);
elem.ani[key].length=0;
if(callback){
callback();
}
}
}
}
window.AniModule={};
window.AniModule.animation=animation;
window.AniModule.stop=stop;
})(window);

工具函数:

(function(){
var root=this;
root._={};
var breaker={};
var ArrayProto=Array.prototype,
ObjProto=Object.prototype,
FuncProto=Function.prototype; var hasOwnProperty=ObjProto.hasOwnProperty; //ECMAScript 5 native function
var nativeForEach=ArrayProto.forEach,
nativeKeys=Object.keys;

_.isIE=!-[1,];
_.keys=nativeKeys||function(obj){
if(obj!==Object(obj)) throw new TypeError('Invalid object');
var keys=[];
for(var key in obj){
if(hasOwnProperty.call(obj,key)){
keys.push(key);
}
}
return keys;
}; _.each=function(obj,iterator,context){
if(obj==null) return;
if(nativeForEach&&obj.forEach===nativeForEach){
obj.forEach(iterator,context);
}else if(obj.length===+obj.length){
for (var i = 0,length=obj.length; i < length; i++) {
if(iterator.call(context,obj[i],i,obj)===breaker) return;
}
}else{
var keys=_.keys(obj);
for(var i=0,length=keys.length;i<length;i++){
if(iterator.call(context,obj[keys[i]],keys[i],obj)===breaker) return;
}
}
}; _.getAppliedStyle=function(elem,styleName){
var style="";
if(styleName== "opacity"&&_.isIE){
style=elem.filters('alpha').opacity/100;
}else if(window.getComputedStyle){
style=elem.ownerDocument.defaultView.getComputedStyle(elem,null).getPropertyValue(toHyphens(styleName));
}else if(elem.currentStyle){
style=elem.currentStyle[toCamelCase(styleName)];
}
function toHyphens(camelCaseValue){
var result=camelCaseValue.replace(/[A-Z]/g,function(c){
return ("-"+c.charAt(0).toLowerCase());
});
return result;
}
function toCamelCase(hyphenatedValue){
var result=hyphenatedValue.replace(/-\D/g,function(c){
return c.charAt(1).toUpperCase();
});
return result;
}
return style;
}; _.setStyle=function(elem,name,value){
if(name=="opacity"&&_.isIE){
elem.style["filter"]="alpha(opacity="+value*100+")";
}else{
elem["style"][name]!==undefined?elem["style"][name]=value:elem[name] = value;
}
};
}).call(this);

调用:animation方法:

window.AniModule.animation(elem,{"left":"+=300px"},{"speed":1000});

stop方法:

window.AniModule.stop(elem);

构造自己的动画函数:animation,stop功能的实现的更多相关文章

  1. 使用原生的javascript封装动画函数(有callback功能)

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  2. [微信小程序] 当动画(animation)遇上延时执行函数(setTimeout)出现的问题

    小程序中当动画animation遇上setTimeout函数内部使用this.setData函数,通常情况下会出现报错.本文先告诉解决方法,后分析报错原因 1.解决方法: 在 setTimeout() ...

  3. Android动画总结#补间动画(Tween Animation/View Animation) #帧动画(Frame Animation/Drawable Animation)#属性动画(PropertyAnimation)

    1.共有三种动画,英文名字多种叫法如下 第一种动画:补间动画(Tween Animation/View Animation) 四个:RotateAnimation旋转. AlphaAnimation透 ...

  4. CSS动画-transition/animation

    HTML系列: 人人都懂的HTML基础知识-HTML教程(1) HTML元素大全(1) HTML元素大全(2)-表单 CSS系列: CSS基础知识筑基 常用CSS样式属性 CSS选择器大全48式 CS ...

  5. android 补间动画和Animation

    介绍: 补间动画是一种设定动画开始状态.结束状态,其中间的变化由系统计算补充.这也是他叫做补间动画的原因. 补间动画由Animation类来实现具体效果,包括平移(TranslateAnimation ...

  6. 移动端 transition动画函数的封装(仿Zepto)以及 requestAnimationFrame动画函数封装(仿jQuery)

    移动端 css3 transition 动画 ,requestAnimationFrame 动画  对于性能的要求,h5优先考虑: 移动端 单页有时候 制作只用到简单的css3动画即可,我们封装一下, ...

  7. CSS3动画以及animation事件

    1.CSS3动画以及animation事件的定义 animation :name duration timing-function delay iteration-count direction an ...

  8. CSS动画:animation、transition、transform、translate

    https://blog.csdn.net/px01ih8/article/details/80780470 一.区分容易混淆的几个属性和值 先区分一下css中的几个属性:animation(动画). ...

  9. 从零开始学 Web 之 BOM(三)offset,scroll,变速动画函数

    大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...

随机推荐

  1. Uiautomator 2.0之Until类学习小记

    1. 状态条件-Uiobject2Condtion 1.1 一个UiObject2Condition代表UiObject2满足某个条件的特定状态,主要用于获取到组件释放处于某种状态. 1.2 简单示例 ...

  2. 使用Ado.net执行SP很慢,而用SSMS执行很快

    今天遇到一个问题,有用户反应,在site上打开报表,一直loading,出不来结果. 遇到这种问题,我立刻simulate用户使用Filter Condition,问题repro,看来不是偶然事件,通 ...

  3. Socket实现仿QQ聊天(可部署于广域网)附源码(4)-加入数据库系统搭建完成

    1.前言 这是本系列的第四篇文章,上一篇我们讲到实现了客户端对客户端的抖屏与收发各种类型文件,本篇文章我们加入SQLServer数据库实现登录与好友的添加等功能,并对界面做了美化处理.向往常一样我会把 ...

  4. 【原创】开源Math.NET基础数学类库使用(10)C#进行基本数据统计

                   本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新  开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...

  5. javascript模拟继承

    javascript作为前端开发的标配技能,如果不掌握好它的三大特点:1.原型 2.作用域 3. 闭包 ,又怎么可以说你学好了这门语言呢?如果标配的技能都没有撑握好,怎么可以任性的玩耍呢?怎么验证自己 ...

  6. golang 字符串操作实例

    package main import s "strings" import "fmt" var p = fmt.Println func main() { p ...

  7. C++ 使用 opencv 库时 Point 在已经引入了 core.hpp 的情况下仍无法识别的可能原因

    引入了 core.hpp 是不够的.请加上 using namespace cv;

  8. 用backbone实现的一个MVC的小demo

    一.Apache配置 本实例需要使用php支持.要现在Apache中配置虚拟目录,在Apache下的httpd-vhosts.conf文件中添加如下代码 <VirtualHost *:80> ...

  9. 1Z0-053 争议题目解析154

    1Z0-053 争议题目解析154 考试科目:1Z0-053 题库版本:V13.02 题库中原题为: 154.A database is running in ARCHIVELOG mode and ...

  10. 「UI 测试自动化selenium」汇总

    <selenium 基础之java实现> selenium RC 环境配置 菜鸟学自动化测试(一)----selenium IDE 菜鸟学自动化测试(二)----selenium IDE ...