构造自己的动画函数:animation,stop功能的实现
最近做一个广告项目,里面涉及很多动画效果,由于不能使用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功能的实现的更多相关文章
- 使用原生的javascript封装动画函数(有callback功能)
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- [微信小程序] 当动画(animation)遇上延时执行函数(setTimeout)出现的问题
小程序中当动画animation遇上setTimeout函数内部使用this.setData函数,通常情况下会出现报错.本文先告诉解决方法,后分析报错原因 1.解决方法: 在 setTimeout() ...
- Android动画总结#补间动画(Tween Animation/View Animation) #帧动画(Frame Animation/Drawable Animation)#属性动画(PropertyAnimation)
1.共有三种动画,英文名字多种叫法如下 第一种动画:补间动画(Tween Animation/View Animation) 四个:RotateAnimation旋转. AlphaAnimation透 ...
- CSS动画-transition/animation
HTML系列: 人人都懂的HTML基础知识-HTML教程(1) HTML元素大全(1) HTML元素大全(2)-表单 CSS系列: CSS基础知识筑基 常用CSS样式属性 CSS选择器大全48式 CS ...
- android 补间动画和Animation
介绍: 补间动画是一种设定动画开始状态.结束状态,其中间的变化由系统计算补充.这也是他叫做补间动画的原因. 补间动画由Animation类来实现具体效果,包括平移(TranslateAnimation ...
- 移动端 transition动画函数的封装(仿Zepto)以及 requestAnimationFrame动画函数封装(仿jQuery)
移动端 css3 transition 动画 ,requestAnimationFrame 动画 对于性能的要求,h5优先考虑: 移动端 单页有时候 制作只用到简单的css3动画即可,我们封装一下, ...
- CSS3动画以及animation事件
1.CSS3动画以及animation事件的定义 animation :name duration timing-function delay iteration-count direction an ...
- CSS动画:animation、transition、transform、translate
https://blog.csdn.net/px01ih8/article/details/80780470 一.区分容易混淆的几个属性和值 先区分一下css中的几个属性:animation(动画). ...
- 从零开始学 Web 之 BOM(三)offset,scroll,变速动画函数
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...
随机推荐
- Sublime Text执行js
Sublime Text执行js 在Build Sytem添加以下内容: { "cmd": ["node", "$file"], " ...
- mysql数据库备份
前一段时间因为误操作删除了一张表的几条数据,弄得很尴尬,正好这周有空就折腾了下数据备份的知识,现把mysql的数据备份相关实践和心得总结如下: 一.使用mysqldump命令备份数据库: 备份整个数据 ...
- ScriptTask读取SharePoint上的Excel
很多情况下,我们会SharePoint 作为文件共享的Server,有时,业务上需要将SharePoint上的Excel文档 Download 到db中.对于搞DB的人来说,难点是如何下载Excel? ...
- MySql事务概述
事务是访问并更新数据库中各种数据项的一个程序执行单元.在事务中的操作,要么都执行修改,要么都不执行,这就是事务的目的,也是事务模型区别于文件系统的重要特征之一. 严格上来说,事务必须同时满足4个特性, ...
- Android随笔之——用shell脚本模拟用户按键、触摸操作
之前写过两篇关于Android中模拟用户操作的博客(其实用一篇是转载的),现在就来讲讲用shell脚本来模拟用户按键操作.本次的目标是用shell脚本打开微信并在其搜索框中搜索相关内容. 本文的模拟功 ...
- JavaWeb:EL表达式
JavaWeb:EL表达式 说明 1.Expression Language语言,一种用于JSP文件中的数据访问的语言. 2.能够简化JSP文件中该数据访问的代码,可用来替代传统的基于<%= % ...
- 深入seajs源码系列二
模块类和状态类 参照上文的demo,我们结合源码分析在简单的API调用的背后,到底使用了什么技巧来实现各个模块的依赖加载以及模块API的导出. 首先定义了一个Module类,对应与一个模块 funct ...
- java之文件基本操作
java之文件基本操作 1 使用 BufferedReader 在控制台读取字符 public static void readChar() throws IOException{ char c; I ...
- Android之自定义ViewPager实现图片的无线轮播
PS:以前也写过关于图片轮播这一块的博客.不过写的很烂,并且很多情况没有考虑到(没有支持无线轮播,和手势点击事件).因此这里写一篇补上.也是当时太年轻了. 注:图片请放大后再看.否则看不清楚. 学习内 ...
- Linux上的SQL Server的起步
我们知道,几个星期前,微软发布了在Linux上直接运行的SQL Server第一个公开CTP版本!因此,对我来说,是时候跨界在Linux上安装我的第一个SQL安装,这样的话,我就可以在Linux上折腾 ...