简单的运动封装函数

简单的运动封装函数

在js的学习当中,我们常常会让元素发生运动,比如说轮播图的渐变效果,元素的左右隐藏显示效果等等,我们每次用到运动的时候重新写一段代码特别的麻烦,我就封装了一段运动函数,每次使用的时候只需要调用一下就可以了

 <style>
        #box{
            width: 100px;
            height: 100px;
            background-color: yellowgreen;
            position: absolute;
            left: 0;
            top: 0;
        }
    </style>
 <div id="box"></div>
    <script>
        // 帧数 :
        var box_ele = document.getElementById("box");
 var timer = null;
        // offset获取元素位置,获取一次即可;
        var box_left = box_ele.offsetLeft;
        // 速度提取出来 ; 
        var speed = 3;
        // 目标点 ;
        var target = 555.5;
        timer = setInterval(function(){
            // 这样的替换实际上就是我们从元素里面取值,赋值变成了对变量进行取值赋值操作;
            box_left += speed;
            box_ele.style.left = box_left + "px"
            // 终止条件;
            if( Math.abs( target - box_left ) <= Math.abs(speed) ){
              	speed = 0;
                clearInterval(timer);
            }
        },30);
 
    </script>

在这里插入图片描述
上面这段代码已经可以实现简单的元素从左到右的运动,但是和我们的目标点有一些误差,这是因为速度可能不一定会被我们所定的距离整除,这样就会产生一定的误差,解决办法很简单,我们可以送他一把:

if( Math.abs( target - box_left ) <= Math.abs(speed) ){
                // 送他一把 : 
                box_ele.style.left = target + "px"
                clearInterval(timer);
            }

在这里插入图片描述

当我们设定的目标点和元素当前距离只差小于速度的时候,我们直接让元素的当前位置等于目标点。
当我们将运动行为放置在一个事件之中时,要在开启定时器之前,先关闭定时器,不然用户多次触发事件时,会造成速度越来越快。甚至元素超出了他的限制范围

 <div id="box">
        <button></button>
    </div>
    <script>
        // 帧数 :
        var box_ele = document.getElementById("box");
        var btn = document.querySelector("button");
        var timer = null;
        // offset获取元素位置,获取一次即可;
        var box_left = box_ele.offsetLeft;
        // 速度提取出来 ; 
        var speed = 3;
        // 目标点 ;
        var target = 500;
        btn.onclick = function(){
            timer = setInterval(function(){
            // 这样的替换实际上就是我们从元素里面取值,赋值变成了对变量进行取值赋值操作;
            box_left += speed;
            box_ele.style.left = box_left + "px"
            // 终止条件;
            
            if( Math.abs( target - box_left ) <= Math.abs(speed) ){
                // 送他一把 : 
                box_ele.style.left = target + "px"
                clearInterval(timer);
            }
        },30);
        }
    </script>

在这里插入图片描述
根据上述代码进行总结之后简单的封装:

 function animate( target , speed ){
            // 根据target 和当前的元素位置判定速度为正数还是负数;
            var iNow = box_ele.offsetLeft;
            // 判定speed是否存在;
            speed = speed === undefined ? 5 : speed;
            // 判定speed的正负;
            speed = iNow < target ? Math.abs(speed) : -Math.abs(speed);
             
            clearInterval(timer)
            timer = setInterval(function(){
                if( Math.abs( target - iNow) <= Math.abs(speed) ){
                    clearInterval(timer);
                    box_ele.style.left = target + "px";
                }else{
                    // 解决了多次出发事件让元素异常运动的bug;
                    iNow += speed;
                    box_ele.style.left = iNow + "px";
                }
            } , 30)
        }

在这里插入图片描述
输入的target是目标到达的位置,speed是元素的速度,将这两个参数传递进来之后,可以根据元素现在的位置和目标点的距离求出速度的正负,如果速度大于了目标点和当前位置只差 就直接让元素到达,反之则当前位置 iNow += speed;根据不断的调试完善这个封装我们可以多输入一个参数,比如元素的width或者是height属性,让元素达到变形的效果

#box{
            width: 200px;
            height: 200px;
            background: #ddd;
            position: absolute;
        }
<div id="box"></div>

 function animate( target , attr , speed ){
            var iNow = parseInt(getComputedStyle(box_ele)[attr]);
            // 判定speed是否存在;
            speed = speed === undefined ? 5 : speed;
            // 判定speed的正负;
            speed = iNow < target ? Math.abs(speed) : -Math.abs(speed);
            clearInterval(timer)
            timer = setInterval(function(){
                if( Math.abs( target - iNow ) <= Math.abs(speed) ){
                    clearInterval(timer);
                    
                    box_ele.style[attr] = target + "px";
                }else{
                   
                    iNow += speed;
                    box_ele.style[attr] = iNow + "px";
                }
            } , 30)
        }
 box_ele.addEventListener("mouseover" , function(){
            animate( 500 , "width" , 10);
        })

在这里插入图片描述
根据每次的需求可以不断的完善自己的封装函数,像是元素属性透明度opacity 也是可以进行改变的,只需要在函数内部判断一下改一下数值可以轻易地做到 渐变的效果。
最后附上比较完善的运动函数封装,仅供大家参考。

function animate( ele , attr_options , callback ){
    for(var attr in attr_options){
        attr_options[attr] = {
            //  目标点 : 传入的数据;
            target : attr === "opacity" ? attr_options[attr] * 100 : attr_options[attr],
            //  元素当前的属性值 ;
            iNow   : attr === "opacity" ? parseInt( getComputedStyle(ele)[attr] * 100 ) : parseInt( getComputedStyle(ele)[attr])
        }
    }
    // 关闭开启定时器;
    clearInterval( ele.timer );
    ele.timer = setInterval( function(){
        // 1. 获取速度; width :  height : 
        for(var attr in attr_options){
            // attr : width | height;
            var item = attr_options[attr];
            // console.log(item , attr);
            var target = item.target;
            var iNow   = item.iNow;
            // 运动所必须的值我们都有了;
            // 计算速度;
            var speed = (target - iNow) / 10;
            // 速度取整;
            speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);

            // 终止条件 : 
            if( Math.abs( target - iNow) <= Math.abs(speed) ){
                // 终止定时器 ; 
                // 送他一把;
                // clearInterval( ele.timer );
                // ele.style[attr] = target + "px";
                // 终止条件不可靠,因为目标的不一致会让运动次数执行不同,有可能提前关闭定时器;
                ele.style[attr] = attr === "opacity" ? target / 100 :  target + "px";
                // 一条运动完成删除对象里面的数据;
                delete attr_options[attr];
                // 如果对象里面没有属性了,那么我们关闭定时器就可以了;
                for(var num in attr_options){
                    // 如果attr_options里面有属性,那么此时我就不应该终止定时器;
                    return false;
                }
                clearInterval(ele.timer);
                typeof callback === "function" ? callback() : "";
            }else{
                // 元素运动;
                // 因为 iNow 是一个临时变量,所以不能再去操作iNow , 要去操作iNow 的数据源;
                // 多花点经历理解这段代码;
                attr_options[attr].iNow += speed;
                ele.style[attr] = attr === "opacity" ? attr_options[attr].iNow / 100 : attr_options[attr].iNow + "px";
            }
        }
    } , 30)
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值