构造自己的动画函数: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 ...
随机推荐
- Android知识——ViewHolder的作用与用法
ViewHolder通常出现在适配器里,为的是listview滚动的时候快速设置值,而不必每次都重新创建很多对象,从而提升性能.在android开发中Listview是一个很重要的组件,它以列表的形式 ...
- ClickOnce部署(5):自定义安全权限
今天我们来探讨一下在ClickOnce部署中如何严格控制应用程序的权限. 演示应用 为了在下文中能更好地演示,我们先要做一个测试项目.也为了显得简单易懂,我使用最常用且最常见的WinForm项目,这是 ...
- 利用typescript使backbone强类型智能提示
模型类一旦多了没有强类型和智能提示是相当痛苦的,所以. 仅仅用ts定义一个模型类: class Person extends Backbone.Model { defaults = { Name:&q ...
- Unity3D研究院之Prefab里面的Prefab关联问题
最近在做UI部分中遇到了这样的问题,就是Prefab里面预制了Prefab.可是在Unity里面一旦Prefab预制了Prefab那么内部的Prefab就失去关联.导致与如果要改内部的Prefab需要 ...
- Android入门(二十一)解析XML
原文链接:http://www.orlion.ga/685/ 解析XML常用的方式有两种,一种是PULL解析一种是SAX解析. 假设解析数据为: <apps> <app> ...
- IOS数据存储之CoreData使用优缺点
前言: 学习了Sqlite数据之后认真思考了一下,对于已经习惯使用orm数据库的开发者或者对sql语句小白的开发者来说该如何做好数据库开发呢?这个上网搜了一下?看来总李多虑了!apple 提供了一种数 ...
- Neutron 功能概述 - 每天5分钟玩转 OpenStack(65)
从今天开始,我们将学习 OpenStack 的 Networking Service,Neutron.Neutron 的难度会比前面所有模块都大一些,内容也多一些.为了帮助大家更好的掌握 Neutor ...
- 3、Redis 基础
Redis的五大数据类型 String(字符串) string是redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value.string类型是二进制安全的.意 ...
- Web前端上万字的知识总结
下面是自己学HTML+DIV+CSS+JS时的学习笔记,给大家分享以下,相互学习.大二时候寒假在家无聊的时候想做点事,总结了一下web前端基础的东西,下面的每个字都是自己手敲的. 1.<html ...
- spring源码分析之cache注解
Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(例如EHCache 或者 OSCache),而是一个对缓存使用的抽象 ...