动画场景

最后更新时间:2023/4/2

抬手动作

人眼看到画布上会动的影像,本质上和看一张照片一样.假如对一个站立的人拍照,那么得到一张站立着的照片,这个人抬起左手后,再拍照,得到

其抬起左手的照片,再放下左手拍照,又得到一张站立着的照片.此时会得到三张照片,在电脑上轮播这三张照片,如果播放速度比较快,那给观看

照片的人感觉就是照片在动,是一个人站立然后抬起左手,然后又放下的动作.

细节

上述是三张照片,可以看到这个人抬左手的动作,如果想看清楚这个人抬起左手的细节,比如抬起时手心在哪,抬起的角度等等,那么有一个办法

就是增加照片数量.可以让这人将抬手动作做得很慢,每抬起一点距离就拍张照片,如此一来可能得到几十张照片.然后将这些照片轮播,此时观看

者感觉到这人的抬手动作比较生动能看到过程.

摄像

上面的办法要求这个人做慢的抬手动作,显然需要有一个变通的办法.就是这个人正常抬手,在拍照时增加频率.简单的说就是在这人抬手动作

过程中,快速的拍照,直到动作完成.那么这样就得到更多的照片.这个过程可叫做摄像,可以认为摄像机在摄像时,其实是在不停的拍照片

摄像过程本质上是拍了很多照片,这些照片可以按某种格式组成一个文件,例如"抬手动画.mp4".那么其中一张照片叫做帧.

这里有个问题,摄像时频率多少合适.如果太高,那么得到的照片很多,文件很大,虽然动作更细腻但太高时人眼也感觉不出了.而太少的话,文件较小

但是动作跨度大,很生硬.显然过多过少都不合适.那么可以设定一个频率,是60.也就是说每秒钟拍摄60张照片比较适宜.

window.requestAnimationFrame()

浏览器用于动画的方法是window.requestAnimationFrame(callback); 参数是一个方法引用,此方法就是绘图方法.对应的还有window.cancelAnimationFrame()

前者调用动画函数,返回值是一个long整数,后者传入这个数可以取消动画.这两个方法是专门为动画而造的.

window.setInterval() 和 window.setTimeout() 两个方法也可做动画,但这两方法并不是因为动画而造的.它们是通用的方法,用于定时指行程序

文档参考 https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestAnimationFrame

回调函数(callback)会被传入DOMHighResTimeStamp参数,DOMHighResTimeStamp指示当前被 requestAnimationFrame() 排序的回调函数被触发的时间.

在同一个帧中的多个回调函数,它们每一个都会接受到一个相同的时间戳,即使在计算上一个回调函数的工作负载期间已经消耗了一些时间.

该时间戳是一个十进制数,单位毫秒,最小精度为1ms(1000μs).


  // 动画函数
  function ani(timestamp){

    // 完成一次动画后,再次调用动画函数,才可以实现连续动画
    window.requestAnimationFrame(ani);

    // 可以每次停顿一秒钟,执行一次动画
    setTimeout(() => {
          window.requestAnimationFrame(ani);
    }, 1000)
  }
  // 调用动画函数
  window.requestAnimationFrame(ani)


其它书签

<<H5核心技术图形动画与游戏开发(David Geary)>>

237页 动画

248页 帧速率的计算逻辑

270页 动画制作最佳指导原则

273页 精灵对象

340页 碰撞检测,分离轴定理

344页 确定投影轴

362页 最小平移量 MTV

直线运动

直线运动比较简单,模拟物体在画布上的直线运动,使用s=vt位移公式,求出每时刻位置,然后绘画出来.距离单位米和画布单位像素设定比例100px=1米

匀速直线运动

长方形物体匀速直线运动,物体长宽 1*0.3, 速度 0.2m/s , 中心点从画布0px位置开始,移动到300px位置,如此重复

关键计算是,由DOMHighResTimeStamp参数计算出每一帧的时间间隔,然后0.2m/s要换算成 0.2 * interval / 1000 ,timeStamp参数单位是

毫秒,然后再累加移动距离,得到当前X轴位置,绘画.下图每走一圈,速度加0.1,加到1再重置为0.2

匀加速直线运动

加速度: 0.2m/平方s

匀速圆周运动