JS实现简单的动画效果 —— 缓动动画的原理

写在前面 

每天都奔赴自己的热爱,是多么幸福的一件事。

唯有美食和理想不可辜负。

CSS中学习了动画,是使用keyframe定义动画,然后添加动画。今天主要是用JS实现动画效果,同时理解动画的原理。emmmm , 本篇文章介绍的是元素移动的效果的原理,其他的还没有了解。见谅见谅哈。

 

动画的原理

动画移动的原理:1.获得元素当前位置;2.每隔一定时间元素位置 加 1;2.使用定时器重复元素位置加1的过程;4.达到目的地时动画停止,动画停止的核心是停止定时器。

动画的核心:是定时器

元素移动,就是元素的偏移量在变化,而且这个变化是有时间限制的,在一定的时间里做出移动的效果。所以移动的核心就是使用定时器实现元素位置的变化。

举个例子:一个盒子,从0平移到500的位置

代码如下

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>动画原理</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        div {
            position: absolute;
            left: 0;
            width: 200px;
            height: 200px;
            background-color: pink;
        }
    </style>
</head>

<body>
    <div></div>
    <script>
        // 动画的原理:定时器
        // 获取元素当前的位置
        // 每隔一定时间元素位置+1
        // 设置定时器重复此动作
        // 要有结束动画的状态:停止定时器 
        // 判断定时器停止的条件 如果还没有到达停止条件就继续执行
        var div = document.querySelector('div');
        var timer = setInterval(function () {
            // 到达目的位置结束定时器
            // 正确写法
            if (div.offsetLeft >= 500) {
                clearInterval(timer);
            } else {
                div.style.left = div.offsetLeft + 1 + 'px';
            }
        }, 15);

        // 错误写法  最后移动的是501px  
        // 应该先判断 再去移动位置
        // div.style.left = divX + 1 + 'px';
        // if (divX == 500) {
        //     clearInterval(timer);
        // }
    </script>
</body>

</html>

其中,我在写的过程中出现了一个错误,就是先让盒子的位移更新,然后去判断是否到达目的地,这样写的话盒子的位移会有偏差,结果是错误的。还有一点是必须要使用if-else语句的,因为就有两种状态要么定时器停止,要么位移更新。 

 

动画函数的封装 

animation函数,两个参数,一个是目标对象,一个是目标位置

在封装时,还有两个问题需要解决。

第一:如果是点击触发动画时,连续点击多次,元素移动的速度会变快;这是因为每点击一次,元素就触发一次定时器,多个定时器同时作用的效果。为了让元素每次调用函数,只保留当前一个定时器,需要在动画函数的第一行先把定时器清除。这样,无论点击多少次,元素的移动的速度都是不变的。

第二:为了使不同的对象调用不同的动画也就是调用不同的定时器,我们在给定时器命名时,使用对象的属性存储定时器

        var div = document.querySelector('div');
        var btn500 = document.querySelector('.btn500');
        // 不同得对象添加定时器  使用对象的属性存储定时器
        // 两个参数:目标对象 目标位置
        function animation(obj, target) {
            // 当多次点击时,盒子移动速度就变得更快 因为每点击一次 就触发了一个定时器
            // 正确做法:应该再调用函数时 定时器应该先被清除 只保留当前一个定时器
            clearInterval(obj.timer);
            obj.timer = setInterval(function () {
                // 到达目的位置结束定时器
                if (obj.offsetLeft >= target) {
                    clearInterval(obj.timer);
                } else {
                    obj.style.left = obj.offsetLeft + 1 + 'px';
                }
            }, 15);
        }

 

动画的回调函数

动画的回调函数:就是在动画的效果完成之后,再执行的函数叫回调函数。

回调函数是在动画函数的第三个参数。

注意:动画的回调函数是写在定时器停止的位置。

 callback的实质:就是把函数作为一个参数传给另一个函数  《====》 callback = function(){}

还是元素移动到500这个例子,但是要加一个效果:元素到达目的时,背景色变为红色。

代码看比较直观

        var div = document.querySelector('div');
        var btn500 = document.querySelector('.btn500');
        var btn800 = document.querySelector('.btn800');

        // 使用对象封装函数 
        // obj 目标对象 target 目标位置  callback回调函数
        // 回调函数:就是把函数作为一个参数传给另一个函数,当动画完成之后才执行的
        function animation(obj, target, callback) {
            // 保持每次调用时 只存在当前一个定时器
            clearInterval(obj.timer);
            obj.timer = setInterval(function () {
                // 到达目的位置结束定时器 目标位置=当前位置
                if (obj.offsetLeft == target) {
                    clearInterval(obj.timer);
                    if (callback) {
                        // 调用函数
                        callback();
                    }
                } else {
                    // 缓动的核心:步长不定 (目标位置 - 现在位置) / 10
                    var step = (target - obj.offsetLeft) / 10; // 是小数  需要得到整数
                    // var step = Math.ceil((target - obj.offsetLeft) / 10);
                    // 判断步长的正负值 三元表达式
                    step = step > 0 ? Math.ceil(step) : Math.floor(step);
                    obj.style.left = obj.offsetLeft + step + 'px';
                }
            }, 40);
        }

        btn500.addEventListener('click', function () {
            animation(div, 500, function () {
                div.style.backgroundColor = 'red';
            });
        })

 

缓动动画

缓动动画的本质就是元素在平移的时候,每次位移量增加的不同,从而实现移动速度的不同,就有移动的速度快慢的效果了。

这里有一个步长的概念,步长公式:步长 = (目标位置 - 当前位置 )/ 10; 这里的10不是定值,可以自己调整。

缓动动画的原理就是在上一个知识点的基础上,把那个每隔一段时间增加的定值1 换位变化的步长实现的。

步长的计算很容易出现小数,这样就会跟实际效果不符合,所以我们需要取整。步长有正有负,代表向前走还是向后退,取整也不同。

步长为正数时:我们向上取整 Math.ceil() 

步长为负数时:我们向下取整 Math.floor()

同样的例子:上面元素移动500都是匀速的,这次让元素缓动移动到目的地。同时还能后退

        // 缓动: 就是动画的速度有变化
        // 原理:
        // 1.移动的距离在变化
        // 2.变化的距离就是步长:
        // 有一个步长的概念:(目标位置 - 现在位置) / 10
        // 3.定时器停止的条件:目标位置=当前位置
        function animation(obj, target) {
            clearInterval(obj.timer);
            obj.timer = setInterval(function () {
                // 到达目的位置结束定时器 目标位置=当前位置
                if (obj.offsetLeft == target) {
                    clearInterval(obj.timer);
                } else {
                    // 缓动的核心:步长不定 (目标位置 - 现在位置) / 10
                    var step = (target - obj.offsetLeft) / 10; // 是小数  需要得到整数
                    // var step = Math.ceil((target - obj.offsetLeft) / 10);
                    // 判断步长的正负值 三元表达式
                    step = step > 0 ? Math.ceil(step) : Math.floor(step);
                    obj.style.left = obj.offsetLeft + step + 'px';
                }
            }, 40);
        }

        var div = document.querySelector('div');
        var btn500 = document.querySelector('.btn500');
        var btn800 = document.querySelector('.btn800');
        btn500.addEventListener('click', function () {
            animation(div, 500);
        })
        btn800.addEventListener('click', function () {
            animation(div, 800);
        })

 

 

动画小案例 —— 滑进滑出效果

需求:鼠标经过时,盒子滑出(向后走),同时在动画完成后,箭头的方向改变;鼠标离开,盒子回去(向前走),箭头变回原来的方向

这个案例是,动画函数回调函数的应用。

代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>引入animation动画</title>
    <script src="animation.js"></script>
    <style>
        .sliderbar {
            position: fixed;
            right: 0;
            bottom: 100px;
            width: 40px;
            height: 40px;
            text-align: center;
            line-height: 40px;
            cursor: pointer;
            color: #fff;
        }

        .con {
            position: absolute;
            left: 0;
            top: 0;
            width: 150px;
            height: 40px;
            background-color: purple;
            z-index: -1;
        }
    </style>
</head>

<body>
    <!-- → -->
    <div class="sliderbar">
        <span>←</span>
        <div class="con">问题反馈</div>
    </div>
    <script>
        // 鼠标经过sliderbar时,出现问题反馈的字样 鼠标离开则不显示
        var sliderbar = document.querySelector('.sliderbar');
        var con = document.querySelector('.con');
        var span = document.querySelector('span');
        sliderbar.addEventListener('mouseover', function () {
            animation(con, -110, function () {
                span.innerHTML = '→';
            });
        })
        sliderbar.addEventListener('mouseleave', function () {
            animation(con, 0, function () {
                span.innerHTML = '←';
            });
        })
    </script>
</body>

</html>

效果图:鼠标经过 鼠标离开

 

ok,今天结束了。 

 

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值