《TypeScript图形渲染实战:2D架构设计与实现》 —3.1.3 基于时间的更新与重绘

举报
华章计算机 发表于 2019/12/12 19:01:31 2019/12/12
【摘要】 本节书摘来自华章计算机《TypeScript图形渲染实战:2D架构设计与实现》 一书中第3章,第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计算机上,会有明显的快慢差别。

  实际上这是一个很固定的流程,将这个动画流程封装起来形成一个类,以后所有的程序都可以使用该类的子类。下一节就来封装这个流程。


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。