zoukankan      html  css  js  c++  java
  • 【原生JS组件】javascript 运动框架

    大家都知道JQuerry有animate方法来给DOM元素进行运动,CSS3中也有transition、transform来进行运动。而使用原生的Javascript来控制元素运动,须要写非常多运动的细节以及兼容。

    然而。当你的BOSS不让你使用庞大的JQ框架,并且你开发的产品也须要在一些不兼容CSS3的浏览器运行的时候。你是否认为每次都要开个定时器来琢磨运动该怎么进行,是件非常费力的事情呢?

    那么福利来了,笔者近期总结了两个经常使用的运动框架,并将其写成组件,
    仅仅要依照以下的方法调用。就可以方便使用。

    1.在你的页面中引入js

    <script src="Mover.js"></script>

    2.在你的js代码中创建Mover对象

    <script>
    window.onload=function(){
        var mover = new Mover();
    };
    </script>

    3.開始使用mover!
    使用方法说明:笔者写的组件包含了两种运动框架供使用。一种是基于速度的;一种是基于时间的。让我们来先看看基于速度的运动框架的使用方法

    startMoveBySpeed(obj, json, endFn);

    參数obj : 传入要运动的对象

    參数json : 以json的形式传入要运动的属性,包含left、top、width、height等以px为单位的属性和透明度opacity,他们的值是运动的终点

    參数endFn(可选) : 结束运动后要运行的方法

    <script>
    //基于速度的运动框架使用方法
    window.onload=function(){
        //得到你要运动的元素
        var oDiv = document.getElementsByTagName('div')[0];
    
        //使用运动框架
        var mover = new Mover();
        oDiv.onclick=function(){    
            mover.startMoveBySpeed(this,{'left':200,'width':300,'opacity':50});
        //使oDiv的left运动到200px,宽度变为300px,透明度变为50%
        }
    
    };
    </script>

    让我们来看看第二种基于时间的运动框架

    startMoveByTime(obj, json, options, endFn )

    參数obj : 传入要运动的对象

    參数json : 以json的形式传入要运动的属性。包含left、top、width、height等以px为单位的属性和透明度opacity。他们的值是运动的终点

    參数options : 以json的形式传入传入运动的总时间和运动方式,如:
    {
    ‘times’ : 1000。//运动总时间为1s
    ‘fx’ : ‘linear’ // 运动形式为匀速
    }
    当options传入參数为空json{}时,就使用默认设置(运动时间500ms,运动形式为匀速)

    參数endFn(可选) : 结束运动后要运行的方法

    //基于事件的运动框架使用方法
    window.onload=function(){
        //得到你要运动的元素
        var oDiv = document.getElementsByTagName('div')[0];
        //使用运动框架
        var mover = new Mover();
        oDiv.onclick=function(){
            mover.startMoveByTime(
                this, 
                {'left':500,'top':200}, 
                {'times':1000,'fx':'easeIn'}, 
                function(){
                    mover.startMoveByTime(this,{'opacity':20},{});
            });
            //使oDiv的left变为500px,高度变为200px,结束上述运动后再使透明度变为20%
        }
    }

    如今来说说两种方式的差别吧。使用第一种方式进行运动时。元素的各项须要改变的属性的运动速度同样,而因为每项属性起点到终点的距离不一样。所以各项属性到达运动终点的时间也不一样。

    而第二种运动直接固定了运动总时间同样,所以全部传入參数的属性一起改变、一起终止。

    以下是Mover.js组件的代码,笔者乃菜鸟一仅仅,欢迎指正。后面有时间也会将弹性运动、碰撞运动、重力运动一起写入框架

    /*
        js原生运动组件
    */
    
    //Mover构造函数
    function Mover(){
        this.setting = {
            'times' : 500,
            'fx' : 'linear'
        }
    }
    
    //获取当前样式
    Mover.prototype.getStyle = function(obj,attr)
    {
        return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj)[attr];
    }
    
    //获取当前时间
    Mover.prototype.now = function(){
            return (new Date()).getTime();
    }
    
    //速度版运动框架
    Mover.prototype.startMoveBySpeed = function (obj,json,fnEnd)
    {
        clearInterval(obj.timer);
        _this = this;
        obj.timer = setInterval(function(){
            obj.bStop = true;
            for(var attr in json)
            {
                var cur = 0;
                var speed = 0;
                if(attr === 'opacity')
                {
                    cur = _this.getStyle(obj,attr);
                    cur = Math.round( parseFloat(cur*100) );
                }
                else
                {
                    cur = parseInt(_this.getStyle(obj,attr));
                }
    
                var speed = (json[attr]-cur)/8;
    
                speed = speed ? Math.ceil(speed):Math.floor(speed);
    
                if(cur !== json[attr])
                {
                    obj.bStop = false;
                }
    
                if(attr === 'opacity')
                {
                    obj.style.opacity = (cur+speed)/100;
                    obj.style.filter = 'Alpha(opacity:'+(cur+speed)+')';
                }
                else
                {
                    obj.style[attr] = (cur+speed)+'px';
                }
            }
    
            if(obj.bStop)
            {
                clearInterval(obj.timer);
                fnEnd && fnEnd.call(obj);
            }
    
        },20);
    }
    
    //时间版运动框架
    Mover.prototype.startMoveByTime = function(obj,json,options,endFn){
        //对于时间版框架来说。初始值b是固定的,所以写在定时器外面
        var _this = this;
        //默认设置
        extend(_this.setting,options);
    
        var iCur = {};
        //获取当前值
        for(attr in json)
        {
            iCur[attr] = 0;
    
            if(attr === 'opacity')
            {
                iCur[attr] = Math.round( parseFloat( _this.getStyle(obj,attr) )*100 );
            }else{
                iCur[attr] = parseInt( _this.getStyle(obj,attr) );
            }
    
        };
    
        var iStartTime = _this.now();
        clearInterval(obj.timer);
        obj.timer = setInterval(function(){
            var iCurTime = _this.now();
            var t = _this.setting.times-
            Math.max(0,iStartTime-iCurTime+_this.setting.times);
            for(attr in json)
            {   
                /*
                    Tween[fx]函数4个參数
                    t:current  time(当前时间)
                    b:beginning  value(初始值)
                    c: change  in  value(变化量)
                    d:duration(持续时间)
                    return  (目标点)   
                */
                var value = _this.Tween[_this.setting.fx](
                    t,                      //t  0~times
                    iCur[attr],             //b
                    json[attr]-iCur[attr],  //c
                    _this.setting.times                     //d
                 );
                if(attr === 'opacity')
                {
                    obj.style[attr] =  parseFloat(value/100);
                    obj.style.filter = 'alpha(opacity:'+value+')';
                }else{
                    obj.style[attr] = value + 'px';
                }
    
            }
    
            if( t === _this.setting.times )
            {
                clearInterval(obj.timer);
                endFn && endFn.call(obj);
            }
        },13);
    
    }
    //覆盖默认设置
    function extend(child,father){
        for(var attr in father)
        {
            child[attr] = father[attr];
        }
    }
    //Tween运动算法
    Mover.prototype.Tween = {
        /*
            4个參数
            t:current  time(当前时间)
            b:beginning  value(初始值)
            c: change  in  value(变化量)
            d:duration(持续时间)
            return  (目标点)
    
        */
    
        linear: function (t, b, c, d){  //匀速
            return c*t/d + b;
        },
        easeIn: function(t, b, c, d){  //加速曲线
            return c*(t/=d)*t + b;
        },
        easeOut: function(t, b, c, d){  //减速曲线
            return -c *(t/=d)*(t-2) + b;
        },
        easeBoth: function(t, b, c, d){  //加速减速曲线
            if ((t/=d/2) < 1) {
                return c/2*t*t + b;
            }
            return -c/2 * ((--t)*(t-2) - 1) + b;
        },
        easeInStrong: function(t, b, c, d){  //加加速曲线
            return c*(t/=d)*t*t*t + b;
        },
        easeOutStrong: function(t, b, c, d){  //减减速曲线
            return -c * ((t=t/d-1)*t*t*t - 1) + b;
        },
        easeBothStrong: function(t, b, c, d){  //加加速减减速曲线
            if ((t/=d/2) < 1) {
                return c/2*t*t*t*t + b;
            }
            return -c/2 * ((t-=2)*t*t*t - 2) + b;
        }
    }
  • 相关阅读:
    vijos 1894 セチの祈り
    luogu p1378 经验之谈
    審視自己
    高斯消去法的相關拓展
    通用汇点
    重征之战
    有文化的人吟了一句诗
    2016年7月总结
    BZOJ 1026: [SCOI2009]windy数
    BZOJ 1047: [HAOI2007]理想的正方形
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/7025924.html
Copyright © 2011-2022 走看看