36. JS动画

我们之前使用CSS实现过动画效果 https://blog.csdn.net/potato123232/category_11644821.html 30,31,32,现在我们使用JS实现

目录

1  动画原理

2  上面动画过程的一点儿bug

3  缓动效果动画

4  多个目标之间移动

5  动画的回调函数

5.1  重复使用回调函数

5.2  不重复使用回调函数

6  带有动画的返回顶部

7  背景随鼠标经过的元素移动


1  动画原理

js动画原理就是通过定时器setInterval()不断修改盒子的样式

比如说想让一个盒子移动,就让他一个像素一个像素的蹭着走

我们下面先搞一个看一看

运行后会发现盒子会从左侧开始移动,移动到400的位置会停下来

有时会有多个元素用到相似的动画,把动画封装成一个函数会让代码看起来更简洁,我们简单封装一下上面的函数

像上面的函数可以甩出来三个参数 执行对象,距离,速度

下面我们用一下

发现可以正常移动

2  上面动画过程的一点儿bug

如果按上面那样写的话执行一次是可以的,现在我们搞一个按钮,我们点一下按钮,动画才会执行

打开页面的时候盒子没动

只点击一次也可以正常到达指定位置

但当我在动画过程中点击多次按钮,那么红色的盒子就会以极快的速度向右走,并且会超出距离限制

这是因为我们每一次点击按钮都会设置一个定时器,我们每次点击按钮时取消上一次的定时器就可以了

这样点了多次他就不会出现刚刚的情况

当红色盒子到达位置的时候,再点击按钮,它还是会往前走一点,这个时候我们加入判断,如果小于距离再加入定时器,如果不小于距离就什么都不做

  • 这里还是会向前走一点的原因是,section使用了相对定位,如果使用相对定位它就不会再向前走了

3  缓动效果动画

缓动效果就是让盒子越走越慢,原理是每次移动的距离随盒子与目标距离的减少而减少

虽然效果不是很明显,但确实执行的是减速运动

但会有一点儿问题,它最终到达的位置不准

所以我们小改一下

这里注意如果要移动到指定的位置,那么你一定要使用绝对位置,如果使用相对位置,每一步就是相对你之前的位置走,那样永远也是走不准的

这里做取整的原因有下面几个

  • 我们的目的地是整数,如果不是整数你就不要取整
  • 如果你不进行取整,它每一次都按小数走,(剩余距离的小数-步长的小数)再除10,小数的位数会越来越多,距离越远越不准
  • 向上取整而不是向下取整的原因,你想一个极端情况,现在你距离终点还差9px,你除以10之后得到你应该走0.9px,这时如果你向下取整,那么你得到的信息就是走0px,所以他到不了指定的位置就动不了了,如果你向上取整就不会有这种问题

4  多个目标之间移动

我们现在加两个按钮,一个点击之后走到500px,另一个点击之后走到800px

先点击500按钮,发现可以成功

再点击800按钮,发现可以从500走到800

这是我再点击500按钮,发现是回不来的,现在我们想让它回来,我们需要取消这里的判断

这样它就可以回来了

由于我们的定位是绝对定位,所以取消了此处的判断,盒子也不会在到达位置的情况下点击后再次移动

回来的时候它会出现一个问题,它走到509就停了

这是因为我们走的是负方向,而且是向上取整,走到只挪动-0.几px时候,直接搞到0,走不动了

这是我们可以对step进行判断

如果正向走就向上取整,如果负向走就向下取整。这样无论是正向走还是负向走就都没有问题了

5  动画的回调函数

回调函数的意思就是返回值是另外一个函数,我们的递归思想就可以使用回调函数实现

5.1  重复使用回调函数

现在我们想让元素在200和500之间来回移动,我们可以这样写

这样它到达200后就可以反复移动了,如果你不想要一开始从0移动到200的过程,那么你把初始位置放在200px就好了

5.2  不重复使用回调函数

如果你要执行一个不重复的回调函数,那么你可以这样写

这样它走到指定位置的时候就会变为红色

这里我们将上面的过程封装成一个函数,移动的动画+动画结束后执行一个函数是比较常用的

function move_animation(obj,distance,callback) {
    clearInterval(obj.timer)
    obj.timer = setInterval(function() {
        step = (distance - obj.offsetLeft)/10
        if (step>0) {
            step = Math.ceil(step)
        }
        else {
            step = Math.floor(step)
        }
        
        obj.style.left = obj.offsetLeft + step + 'px'
        if (obj.offsetLeft == distance) {
            clearInterval(obj.timer)
            if (callback) {
                callback()
            }
        }
        
    },15)
}

6  带有动画的返回顶部

上一章我们做了这个

这里我们给回顶部加上动画效果,首先我们修改一下动画的代码

  • 这个obj还是留着好,在消除定时器的时候,如果你在赋值前就消除会报错

之后进行调用

将该段代码拿到移动端上使用同样可以生效

点击后可以以动画形式运动返回顶部

7  背景随鼠标经过的元素移动

有下面三个功能

鼠标经过某一个li的时候,产生动画跟到li的位置

点击哪个li,哪个li的文字就变绿

离开ul时,会做动画回到绿色字体li的地方

<!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>
    <link rel="stylesheet" href="initialization.css">
    <style>
        ul {
            display: flex;
            width: 300px;
            height:50px;
            justify-content: space-around;
        }

        li {
            width:60px;
            height:50px;
            border:1px solid red;
            font-size:36px;
        }

        span {
            position: absolute;
            top:0px;
            width:60px;
            height:50px;
            background-color: rgba(255, 0, 0, 0.3);
            z-index: -1;
        }

        .current_li {
            color: green;
        }

    </style>
</head>
<body>
    <ul>
        <li class="current_li">1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    <span></span>
</body>
<script src="animation.js"></script>
<script>
    ul = document.querySelector('ul')
    span = document.querySelector('span')

    background_width = 60

    all_lis = ul.children

    which_li = 0
    for (i=0;i<all_lis.length;i++) {
        all_lis[i].index = i
        all_lis[i].distance = i * background_width
        all_lis[i].addEventListener('mouseenter',function() {move_animation(span,this.distance)})
        all_lis[i].addEventListener('click',function() {
            which_li = this.index
            for (i=0;i<all_lis.length;i++) {
                all_lis[i].className = ''
            }
            this.className = 'current_li'
        })
        all_lis[i].addEventListener('mouseleave',function() {move_animation(span,all_lis[which_li].distance)})
    }
</script>
</html>

初始化CSS的代码可以在这里找到 21.CSS初始化_Suyuoa的博客-CSDN博客 


版权声明:本文为potato123232原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。