构造自己的动画函数: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 ...
随机推荐
- 【夔堂】:程序血泪史之——有一种垃圾语言叫做JavaScript
"Prototype"机制是个半成品OOP,有些文章说这玩意当初为了"简单(编写).容易(学习)"而发明的,但web前端技术发展到今天我们看到,JS显然是需要O ...
- html中定义标签字母的大小写
定义和用法: text-transform 属性控制文本的大小写. 值和属性: 值 描述 none 默认.定义带有小写字母和大写字母的标准的文本. capitalize 文本中的每个单词以大写字母开头 ...
- HTML5应用缓存机制
首先先上一张图: 用360浏览器的用户对这张图应该都是耳熟能详了吧,没错,当网络不通畅时使用360浏览器,便会有这张图弹出来.为什么没有网络还能弹出这一副画面呢?这就关乎HTML5的应用缓存机制了. ...
- fix orphaned user
orphan user是某个数据库的user,只有user name而没有login,即,在存在于sys.database_principals 中, 而不存在于 sys.server_princip ...
- Linq语法详细
闲言碎语 近期比较忙,但还是想写点什么,就分享一些基础的知识给大家看吧,希望能帮助一些linq新手,如果有其它疑问,可以进右上角群,进行交流探讨,谢谢. 开门见山 读这篇文章之前,我先说下,每一种搜索 ...
- C# 获取当前月第一天和最后一天 计算两个日期差多少天
获取当前月的第一天和最后一天 DateTime now = DateTime.Now; DateTime firstDay = ); DateTime lastDay = firstDay.AddMo ...
- JavaScript知识 一、JS的数据类型
一.JS的数据类型 1.基本类型 JS共有5大基本类型,分别是: 1)Undefined.他只有一个值:undefined.如果一个变量被定义但是没有给他赋值,那么这个时候系统会默认给这个变量赋值为u ...
- Java-Spring:java.lang.ClassCastException: com.sun.proxy.$Proxy* cannot be cast to***问题解决方案
java.lang.ClassCastException: com.sun.proxy.$Proxy* cannot be cast to***问题解决方案 临床表现: 病例: 定义代理类: @Tra ...
- Oracle 11g安装GI后,运行roothas.pl脚本报错libcap.so.1找不到
环境:RHEL6.4 + Oracle 11.2.0.3问题:需求是文件系统迁移到ASM,在安装GI后,运行roothas.pl脚本报错 1.运行root.sh后,按提示运行roothas.pl报错 ...
- php中调用WebService接口
一.背景 调用第三方短信提供商的WebService接口. 二.介绍 1.WebService三要素: SOAP(Simple Object Access Protocol) 用来描述传递信息的格式 ...