构造自己的动画函数: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);

转载于:https://www.cnblogs.com/mufc-go/p/3443807.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值