zoukankan      html  css  js  c++  java
  • 构造自己的动画函数: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);

  • 相关阅读:
    cmanformat
    mysql-sql语言参考
    jQuery 判断多个 input checkbox 中至少有一个勾选
    Java实现 蓝桥杯 算法提高 计算行列式
    Java实现 蓝桥杯 数独游戏
    Java实现 蓝桥杯 数独游戏
    Java实现 蓝桥杯 数独游戏
    Java实现 蓝桥杯 算法提高 成绩排序2
    Java实现 蓝桥杯 算法提高 成绩排序2
    Java实现 蓝桥杯 算法提高 成绩排序2
  • 原文地址:https://www.cnblogs.com/mufc-go/p/3443807.html
Copyright © 2011-2022 走看看