前端JavaScript

复习笔记之API(15) JS动画

2020-04-22  本文已影响0人  晚月川

[TOC]

JS中的动画

动画实现原理

  • 核心原理:通过定时器setInterval()不断移动盒子的位置
  • 实现步骤:
    • 获得当前盒子位置
    • 让当前盒子位置加一个移动距离
    • 利用定时器不断重复这个操作
    • 加一个结束定时器的条件
    • 注意此元素需要添加定位,才能使用element.style.left
<style>
    div {
        position: absolute;
        left: 0;
        top: 0;
        width: 200px;
        height: 200px;
        background-color: black;
    }
</style>
<div></div>
<!-- IMPORT JS -->
<script>
    let div = document.querySelector('div');
    let timer = setInterval(function () {
        if (div.offsetLeft == 400) {
            // 停止动画 本质就是停止定时器
            clearInterval(timer);
        }
        div.style.left = div.offsetLeft + 1 + 'px';
    }, 30);
</script>

动画函数的封装

注意函数需要传递两个参数,动画对象和移动到的距离

// 简单动画函数封装 obj目标对象 target目标位置
function animate(obj, target) {
    let timer = setInterval(function () {
        if (obj.offsetLeft == target) {
            // 停止动画 本质就是停止定时器
            clearInterval(timer);
        }
        obj.style.left = obj.offsetLeft + 1 + 'px';
    }, 30);
}

动画函数给不同元素记录不同的定时器:如果多个元素都使用这个动画函数,我们可以给不同的元素使用不同的定时器(自己专用自己的定时器)

  • 核心原理:利用JS是一门动态语言,可以很方便的给当前对象添加属性
<style>
    div {
        position: absolute;
        width: 200px;
        height: 200px;
        background-color: black;
    }

    span {
        position: absolute;
        left: 0;
        top: 300px;
        display: block;
        width: 100px;
        height: 100px;
        background-color: blue;
    }
</style>
<div></div>
<span></span>
<script>
    // 给不同元素设置了不同的定时器
    function animate(obj, target) {
        obj.timer = setInterval(function () {
            if (obj.offsetLeft >= target) {
                // 停止动画 本质就是停止定时器
                clearInterval(obj.timer);
            }
            obj.style.left = obj.offsetLeft + 1 + 'px';
        }, 30);
    }
    animate(div, 300);
    animate(span, 500);
</script>

优化一下:添加一个按钮,当点击按钮的时候,动画开始

  • 这时会发现一个问题,当我们不断点击按钮的时候,这个元素运动会越来越快,因为开启了太多的定时器
  • 解决方案:让元素只有一个定时器执行
<style>
    div {
        position: absolute;
        width: 200px;
        height: 200px;
        background-color: black;
    }

    span {
        position: absolute;
        left: 0;
        top: 300px;
        display: block;
        width: 100px;
        height: 100px;
        background-color: blue;
    }
</style>
<button>点击开始赛跑</button>
<div></div>
<span></span>
<script>
    let div = document.querySelector('div'),
        span = document.querySelector('span'),
        btn = document.querySelector('button');
     function animate(obj, target) {
        //  先清楚以前的定时器,只保留当前的一个定时器执行
        clearInterval(obj.timer);
        obj.timer = setInterval(function () {
            if (obj.offsetLeft >= target) {
                // 停止动画 本质就是停止定时器
                clearInterval(obj.timer);
            }
            obj.style.left = obj.offsetLeft + 1 + 'px';}
        }, 30);
    btn.addEventListener('click', function () {
        animate(div, 300);
        animate(span, 500);
    })
</script>

缓动效果

缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来

  • 思路:
  1. 让每次移动距离慢慢变小,速度就会慢慢落下来
  2. 核心算法:(目标值 - 现在位置) / 10 作为每次移动的距离步长
  3. 停止的条件是:让当前盒子位置等于目标位置就停止定时器
<style>
    div {
        position: absolute;
        width: 200px;
        height: 200px;
        background-color: black;
    }

    span {
        position: absolute;
        left: 0;
        top: 300px;
        display: block;
        width: 100px;
        height: 100px;
        background-color: blue;
    }
</style>
<button>点击开始赛跑</button>
<div></div>
<span></span>
<script>
    let div = document.querySelector('div'),
        span = document.querySelector('span'),
        btn = document.querySelector('button');
     function animate(obj, target) {
        clearInterval(obj.timer);
        obj.timer = setInterval(function () {
            // 步长值写到定时器的里面
            let step = (target - obj.offsetLeft) / 10;
            if (obj.offsetLeft == target) {
                // 停止动画 本质就是停止定时器
                clearInterval(obj.timer);
            }
            obj.style.left = obj.offsetLeft + step + 'px';
        }, 15);
    }
    btn.addEventListener('click', function () {
        animate(div, 1000);
        animate(span, 800);
    })
</script>
  • 匀速动画就是 盒子当前的位置 + 固定的值
  • 缓动动画就是 盒子当前位置 + 变化的值 ((目标值 - 现在位置) / 10)

这个缓动动画并不完美,因为每次都不能准确的到达终点,因为前面的公式中有除法的存在,所以难以避免最后出现小数,为了解决这个问题,我们就需要吧步长值改为整数,所以可以利用数学函数中的Math.ceil()向上取整一下(如果考虑到动画还有后退的过程,就需要向下取整Math.floor())

<style>
    div {
        position: absolute;
        width: 200px;
        height: 200px;
        background-color: black;
    }
</style>
<button class="one">跑到500的位置</button>
<button class="two">跑到1000的位置</button>
<div></div>
<script>
    let div = document.querySelector('div'),
        btn = document.querySelector('.one'),
        btn2 = document.querySelector('.two');
    function animate(obj, target) {
        clearInterval(obj.timer);
        obj.timer = setInterval(function () {
            // 步长值写到定时器的里面
            let step = (target - obj.offsetLeft) / 10;
            step = step > 0 ? Math.ceil(step) : Math.floor(step);
            if (obj.offsetLeft == target) {
                // 停止动画 本质就是停止定时器
                clearInterval(obj.timer);
            }
            obj.style.left = obj.offsetLeft + step + 'px';
        }, 15);
    }
    btn.addEventListener('click', function () {
        animate(div, 500);
    })
    btn2.addEventListener('click', function () {
        animate(div, 1000);
    })
</script>

动画函数多个目标值之间的移动,我们需要判断步长值正数还是负数

  • 如果是正数,则步长往大了取整
  • 如果是负的,则步长往小了取整
上一篇 下一篇

猜你喜欢

热点阅读