2022-05-07 运动函数封装:从缓冲运动抽象出封装的运动函数

一.缓冲运动
需求

小球下落的过程中速度逐渐变小,到达底部时速度变为零

要点

通过实时比较运动总路程box.offsetHeight-ball.offsetHeight.
和ball.offsetTop(小球距离box顶部的距离)
把两者之差赋给变量speed,
就可以得到一个ball.offsetTop不断增加,
speed有初始值但不断减小至0的运动过程

完整代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <style>
        .box {
            position: relative;
            width: 300px;
            height: 500px;
            background-color: antiquewhite;
        }
        
        #ball {
            position: absolute;
            left: 0;
            top: 0;
            width: 50px;
            height: 50px;
            background-color: blue;
            border-radius: 50%;
            margin: 0px;
        }
    </style>
    <div class="box">
        <dov id="ball"></dov>
    </div>
    <script>
        var ball = document.querySelector("#ball");
        var box = document.querySelector(".box");
        var timer = null;
        var target = box.offsetHeight - ball.offsetHeight;
        ball.onclick = function() {
            clearInterval(timer);
            timer = setInterval(() => {
                var speed = (target - ball.offsetTop) / 10; //ball.offsetTop增大,speed减小
                speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); //保持四舍五入整数
                // console.log(speed);
                if (ball.offsetTop + speed >= target) {
                    clearInterval(timer);
                } else {
                    ball.style.top = ball.offsetTop + speed + "px";
                }
            }, 100);
        }
    </script>
</body>
</html>
重点代码
var ball = document.querySelector("#ball");
var box = document.querySelector(".box");
var timer = null;
var target = box.offsetHeight - ball.offsetHeight;
ball.onclick = function() {
    clearInterval(timer);
    timer = setInterval(() => {
        var speed = (target - ball.offsetTop) / 10; //ball.offsetTop增大,speed减小
        speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); //保持四舍五入整数
        // console.log(speed);
        if (ball.offsetTop + speed >= target) {
            clearInterval(timer);
        } else {
            ball.style.top = ball.offsetTop + speed + "px";
        }
    }, 100);
    // move(ball);
}
二.把其运动过程封装成一个move函数

只需要在鼠标点击事件中调用这个函数就行了

重点代码
var ball = document.querySelector("#ball");
var box = document.querySelector(".box");
ball.onclick = function() {
    move(ball);
}
//封装缓冲运动的函数
function move(ele) {
    var times = null;
    var target = box.offsetHeight - ele.offsetHeight;
    clearInterval(times);
    times = setInterval(() => {
        var alpha = ele.offsetTop;
        var speed = Math.ceil((target - alpha) / 10); //只读属性上偏移量alpha增大,speed减小
        console.log(`运动路程:${target},当前路程:${alpha},当前速度:${speed}`);
        if ((alpha + speed) > target) {
            ele.style.top = target + 'px';
        } else {
            ele.style.top = speed + alpha + 'px';
        }
        if (Math.abs(speed) < 1) clearInterval(times);
    }, 30);
}
三.封装一个抽象的,适配性更高的运动函数

封装一个运动函数,让其适配不止一种运动情况,
不仅仅可以满足元素的高度发生改变这样的一种情况,
让以元素的其他属性(宽高背景色透明度等等)的改变为基础的运动事件都可以用得上

*注意getStyle的形参应该是ele,也就是div对象,而不是obj(即元素属性)

代码
//运动函数封装
var timer = null;
//ele:运动元素如div,obj:div元素的属性和属性值构成的对象,cb:callback回调函数
function move(ele, obj, cb) {
    //定时器先清除再调用
    clearInterval(timer);
    timer = setInterval(() => {
        // 设置一个清除定时器与否的开关
        var onOff = false;
        // 遍历运动属性obj[i],如width,height,opacity,backgroundColor等等
        for (var attr in obj) {//attribute:属性
            // 获取运动元素的实时运动属性值
            //var tmpPos = parseInt(window.getComputedStyle(obj[attr])); //100px,red等等可能的属性值
            //考虑IE兼容,封装成一个函数getStyle
            var tmpPos =parseInt(getStyle(ele,attr));
            // 计算speed
            var speed = (obj[attr] - tmpPos) / 10; //属性的目标值(如前例的target)-属性的当前值(如前例的alpha),除以10 是为了提高运动过程的精细程度
            speed > 0 ? Math.ceil(speed) : Math.floor(speed); //因为除以10可能会产生小数,因此|speed|向上取整
            // 更新运动属性
            ele.style[attr] = tmpPos + speed + "px"; //举例:div.style.width
            // 判断达到目标值
            if ((speed + tmpPos) == obj[attr]) onOff = true;
        }
        // 判断开关,写在for循环外面
        if (onOff) clearInterval(timer);
    }, 30);
}
function getStyle(ele,attr)(
	if(ele.currentStyle[attr]) return ele.currentStyle[attr];//兼容IE
	else return getComputedStyle(ele)[attr];//通用
)
四.调用运动函数应用场景
<div id="box" style="width:50px;height:50px;position:absolute;background:red;border-radius: 50%;left:100px;">
</div>
<script>
    // 获取节点
    let boxObj = document.getElementById('box');
    boxObj.onclick = function() {
        move(this, { //调用运动函数
            top: 400
        }, function() {
        alert("运动完成!");
        });
    };
    // 运动三要素:元素 目标 属性
    function move(eleObj, objArr, callback) {
        var timer = '';
        // 使用之前先清空定时器
        clearInterval(timer);
        timer = setInterval(() => {
            // 设置清除定时器的判断开关
            var onOff = false;
            // 遍历运动元素的属性
            for (var attr in objArr) {
                // 获取元素的实时属性值
                var tmpPos = parseInt(getStyle(eleObj, attr)); //调用getStyle
                // 计算speed
                var speed = (objArr[attr] - tmpPos) / 10;
                speed > 0 ? Math.ceil(speed) : Math.floor(speed);
                // 更新运动属性:让元素开始运动
                eleObj.style[attr] = speed + tmpPos + 'px';
                // 判断临界值
                if (speed + tmpPos == objArr[attr]) onOff = true;
            }
            // 判断清空定时器
            if (onOff) {
                clearInterval(timer);
                // 如有回调函数就调用
                if (callback) return callback();
            }
        }, 30);
    }
    // 获取元素实时的属性值
    function getStyle(obj, attr) {
        if (obj.currentStyle) return obj.currentStyle[attr]; //兼容IE
        else return getComputedStyle(obj)[attr]; //通用
    }
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端OnTheRun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值