缓动动画,步长无变化情况,定时器不能停下

        看了pink老师的缓动动画制作,需要完成一个盒子从起点到800px,再回到500px,且离终点越近速度减慢,即做到 缓动效果。

图1 是要完成的效果图,盒子到达固定位置就停下,且定时器也停下,还能实现倒退,有明显的速度减慢。

 我一开始的问题是,盒子不仅停不下来,还飞到无穷远的地方去了!

这是第一次写的问题多多代码,😓

<style>
        .box {
            position: absolute;
            margin-top: 40px;
            width: 50px;
            height: 50px;
            background-color: palegreen;
        }
    </style>
</head>

<body>
    <div class="box"></div>
    <button class="btn5">到五百</button>
    <button class="btn8">到八百</button>
    <script>
        var box = document.querySelector('.box');

        function animate(obj, target) {
            clearInterval(obj.timer);

            var step = (target - obj.offsetLeft) / 10;
            obj.timer = setInterval(function() {

                if (obj.offsetLeft == target) {
                    clearInterval(obj.timer);
                }
                obj.style.left = obj.offsetLeft + step + 'px';
            }, 20)
        }
        var btn5 = document.querySelector('.btn5');
        var btn8 = document.querySelector('.btn8');

        btn5.addEventListener('click', function() {
            animate(box, 500);
        })
        btn8.addEventListener('click', function() {
            animate(box, 800);
        })
    </script>
</body>

</html>

 后来我发现给盒子的left属性赋值为0,可以完成一次动画效果,但是等第二次按下按钮还是不能到达指定位置,而且还没有缓动效果。

加入调试代码,分别打印了,盒子的offsetLeft值、定时器是否停止(target 目标值是否达到)、步长是多少。以下为运行结果图

可以看到几个问题:

一、步长没有发生变化,一直都是一个数字,猜测很有可能是 obj.offsetLeft没有动态获取到盒子的偏移值。

二、定时器只停下了两次,也就是在第一次按下500、800的按钮时,再次点击无效,猜测target目标位置永远没有到达,所以定时器一直停不下来

解决问题:

这里的步长没有发生变化,我觉得可能是,offsetLeft只获取了一次偏移值,就只使用了一次这个公式计算(目标值-现在位置) / 10 = 每次移动的步长 ,因此算得的步长值自然没有变换,把计算步长的代码放到定时器里面,每完成一次动画,就再计算一次,这样就可以获得动态的offsetLeft值了

再者,到达不了目标值,定时器不会停止,是因为我们使用的计算步长的公式有除法,商数极有可能是有小数的,小数一直除下去就没完没了了,因此加入取整的代码。

这里想到过直接用 parseInt()这个方法,  var step = parseInt((target - obj.offsetLeft) / 10);  还是会出现无法到达目标位置的情况,除到商小于1的时候,parseInt()取整的结果是0,可目标位置远没到达,此方法不可行。


     最合适的还是用向上取整公式Math.ceil(),但是若只向上取整,那么盒子在倒退的时候有会有问题,这时候的target - offsetLeft < 0,负数向上取整,-9.9向上取整得到-9,盒子本应该前进9.9,向上取整盒子后退的距离就会小。

所以当盒子后退的时候,也就是step < 0时,步长应该向下取整,再使用三目运算加入判断就可以啦! step = step > 0 ? Math.ceil(step) : Math.floor(step);

加入步长判断后,可以看到没有到达目标位置前,步长都是正整数、负整数。

 

小结一下: 

使用offsetLeft记得给盒子加上position属性,left也要赋值为0;

每执行一次定时器就要重新获取偏移值,这样才能动态计算步长;

对于位移问题,盒子移动的距离取的是绝对值,负数向下取整绝对值才大,才不会出现没有到达目标位置,步长就为0 的情况。

        function animate(obj, target) {
            clearInterval(obj.timer);
       
            obj.timer = setInterval(function() {
                console.log('偏移:' + obj.offsetLeft);
                var step = (target - obj.offsetLeft) / 10;
                step = step > 0 ? Math.ceil(step) : Math.floor(step);
                if (obj.offsetLeft == target) {
                    clearInterval(obj.timer);
                    console.log('stop');
                }
                obj.style.left = obj.offsetLeft + step + 'px';
                console.log('步长: ' + step);
            }, 20)
        }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值