JS帧动画

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/DreamFJ/article/details/81866867

什么是帧动画

  • 所谓帧动画就是在“连续的关键帧”中分解动画动作,也就是在时间轴的每帧上逐帧绘制不同的内容,使其连续播放而成动画。
  • 由于帧动画是一帧一帧的画,所以帧动画具有非常大的灵活性,几乎可以表现任何想表现的内容。

常见的帧动画方式

  • GIF
  • CSS3 animation
  • Javascript

GIF和CSS3 animation实现帧动画的不足

  1. 不能灵活的控制动画的暂停和播放(GIF、CSS3 animation)
  2. 不能捕捉到动画完成的事件(GIF)
  3. 不能对帧动画做更加灵活的扩展(GIF、CSS3 animation)

JS实现帧动画的原理

  1. 如果有多张帧图片,用一个image标签去承载图片,然后定时改变image的src属性(不推荐,相当于请求了多张图片,会发送多个http请求
  2. 把所有动画关键帧绘制在一张图片里,把图片作为元素的backgroud-image,定时改变元素的background-position属性(推荐,只有一个http请求

eg:

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>JS实现帧动画</title>
    <style type="text/css">
        #rabbit {
            width: 102px;
            height: 80px;
        }
    </style>
</head>

<body>
    <div id="rabbit"></div>
    <script type="text/javascript">
        // 做一个兔子不停原地奔跑的帧动画,每一帧都放在一张大图里
        var rabbit = document.getElementById("rabbit");

        // 获取每一帧在图片中对应的位置
        var positions = ['0 -854', '-174 -852', '-349 -852', '-524 -852', '-698 -852', '-873 -848'];

        // 设置兔子的背景图片
        rabbit.style.backgroundImage = 'url(rabbit.png)';
        rabbit.style.backgroundRepeat = 'no-repeat';

        // 每隔一段时间改变背景图片的位置
        var index = 0;

        function run() {
            var position = positions[index].split(' ');
            rabbit.style.backgroundPosition = position[0] + 'px ' + position[1] + 'px';
            index++;
            if (index >= positions.length) {
                index = 0;
            }
            setTimeout(run, 80);
        }

        run();
    </script>
</body>

</html>

问题:在用setTimeout模拟setInterval时,怎么清除定时器?菜鸟上说要在全局定义定时器,但是不是递归调用的吗?能清除所有的定时器吗?感觉只能清除一个呀。


ps:这是从慕课网上学的js帧动画课程,后面还有教你怎么去封装这样一个帧动画,虽然看懂了,但是我什么时候也能写出这样的代码来呀,逻辑清晰,复用性强,鲁棒性强。

他从需求分析->编程接口->调用方式->代码设计这四个步骤一步一步来,但是我都不知道要定义哪些接口。。。

需求分析

  • 支持图片预加载(图片的加载是一个异步过程,如果在动画执行过程中图片还没被下载下来的话,会导致动画的前几帧都是空白图片,所以我们要保证动画执行的时候图片是已经被下载好的)
  • 支持两种动画播放方式,及自定义每帧动画
  • 支持单组动画控制循环次数(可支持无限次)
  • 支持一组动画完成,进行下一组动画
  • 支持每个动画完成后有等待时间
  • 支持动画暂停和继续播放
  • 支持动画完成后执行回调函数

编程接口

  • loadImage(imglist) //预加载图片

  • changePosition(ele,positions,imageUrl) //通过改变元素的background-position实现动画

  • changeSrc(ele,imglist) //通过改变image元素的src

  • enterFrame(callback) //每一帧动画执行的函数,相当于用户可以自定义每一帧动画的callback

  • repeat(times) //动画重复执行的次数,times为空时表示无限次

  • repeatForever() //无限重复上一次动画,相当于repeat(),更友好的一个接口吧

  • wait(time) //每个动画执行完后等待的时间

  • then(callback) //动画执行完成后的回调函数

  • start(interval) //动画开始执行,interval表示动画执行的间隔

  • pause() //动画暂停

  • restart() //动画从上一次暂停处重新执行

  • dispose() //释放资源

调用方式

  • 支持链式调用,我们期望动词的方式描述接口,调用方式如下:

    var animation = require("animation");
    var demoAnimation=animation().loadImage(images).changePosition(ele,positions).repeat(2).then(function(){
        /*动画执行完成后调此函数*/
    });
    demoAnimation.start(80);

代码设计 

  • 我们把“图片预加载->动画执行->动画结束”等一系列操作看成一条任务链(数组)

    • 任务链有两种类型的任务:a.同步执行完毕的;b.异步定时执行的(通过计时器或者raf)。

  • 记录当前任务链的索引

  • 每个任务执行完毕后,通过调用next方法,执行下一个任务,同时更新任务链索引值

图解任务链

猜你喜欢

转载自blog.csdn.net/DreamFJ/article/details/81866867