《TypeScript图形渲染实战:2D架构设计与实现》 —3.1.3 基于时间的更新与重绘
3.1.3 基于时间的更新与重绘
现在有一个很简单的需求,假设想让一个物体(例如一个矩形或圆球)沿着水平轴(x轴),以每秒10个像素的速度进行移动,那么应该怎么做呢?
其实这里涉及两个基本步骤,让物体进行基于时间(每秒10个像素)的更新,以及更新完后进行显示。
让我们来搭建一个最简单的更新与重绘框架。上一节中,在step回调函数中已经计算出了3个以毫秒表示的时间间隔(时间差),即:
* 当前时间点与当前HTML应用启动时的时间差 timestamp。
* 当前时间点与第一次调用step回调函数时的时间差 elapsedMsec。
* 当前时间点与上一次调用step回调函数时的时间差 intervalMsec。
以上3个时间间隔或时间差中最有用的是第3个时间差,特别适合做基于时间的更新。那么声明一个函数用于更新操作,演示代码如下:
let posX : number = 0 ;
let speedX : number = 10 ; //单位为秒,以每秒10个像素的速度进行位移
function update ( timestamp : number , elapsedMsec : number , intervalMsec :
number ) : void {
// 参数都是使用毫秒为单位,而现在的速度都是以秒为单位
// 因此需要将毫秒转换为秒来表示
let t : number = intervalMsec / 1000.0 ;
// 线性速度公式 : posX = posX + speedX * t ;
posX += speedX * t ;
console . log ( " current posX : " + posX ) ;
}
关于渲染,输入如下代码:
// 使用CanvasRenderingContext2D绘图上下文渲染对象进行物体的绘制
function render ( ctx : CanvasRenderingContext2D | null ) : void {
// 简单起见,仅仅输出render字符串
console . log ( " render " ) ;
}
最后,将这两个函数由step函数进行调用,就可以形成一个基本的框架。具体代码如下:
// start记录的是第一次调用step函数的时间点,用于计算与第一次调用step函数的时间差,
以毫秒为单位
let start : number = 0 ;
//lastTime记录的是上一次调用step函数的时间点,用于计算两帧之间的时间差,以毫秒为单位
let lastTime : number = 0 ;
// count用于记录step函数运行的次数
let count : number = 0 ;
// step函数用于计算
// 1.获取当前时间点与HTML程序启动时的时间差 : timestamp
// 2.获取当前时间点与第一次调用step时的时间差 : elapsedMsec
// 3.获取当前时间点与上一次调用step时的时间差 : intervalMsec
function step ( timestamp : number ) {
//第一次调用本函数时,设置start和lastTime为timestamp
if ( ! start ) start = timestamp ;
if( ! lastTime) lastTime = timestamp ;
//计算当前时间点与第一次调用step时间点的差
let elapsedMsec = timestamp - start ;
//计算当前时间点与上一次调用step时间点的差(可以理解为两帧之间的时间差)
let intervalMsec = timestamp - lastTime ;
//记录上一次的时间戳
lastTime = timestamp ;
// 进行基于时间的更新
update ( timestamp , elapsedMsec , intervalMsec ) ;
// 调用渲染函数,目前并没有使用CanvasRenderingContext2D类,因此设置为null
render ( null ) ;
// 使用requestAnimationFrame调用step函数
window . requestAnimationFrame ( step ) ;
}
// 使用requestAnimationFrame启动step
// 而step函数中通过调用requestAnimationFrame来回调step函数
// 从而形成不间断地递归调用,驱动动画不停地运行
window . requestAnimationFrame ( step ) ;
当运行上述代码后,会发现每次调用step回调函数后,posX总是根据传入的时间差进行更新,这样的好处不管在哪个浏览器中或是不同运行速度的计算机上,每秒钟的运动距离都是恒定的(每秒10像素)。如果不使用基于时间的更新,那么在不同浏览器中不同的CPU计算机上,会有明显的快慢差别。
实际上这是一个很固定的流程,将这个动画流程封装起来形成一个类,以后所有的程序都可以使用该类的子类。下一节就来封装这个流程。
- 点赞
- 收藏
- 关注作者
评论(0)