开发者社区> 华章计算机> 正文

《HTML5 2D游戏编程核心技术》——第3章,第3.2节实现平滑的HTML5动画

简介:
+关注继续查看

本节书摘来自华章出版社《HTML5 2D游戏编程核心技术》一书中的第3章,第3.2节,作者[美] 戴维·吉尔里,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

3.2 实现平滑的HTML5动画
简单地说,编程实现动画效果是简单的:你不断地绘制一个图像序列,产生图像正在以某种方式运动的效果。同样,这也意味着你需要实现一个能够持续绘制图像的循环。
传统的做法是,动画循环在JavaScript中使用setTimeout()函数或者使用程序清单3.4描述的setInterval()函数来实现。
如果实现了一个draw()函数来绘制下一个动画帧,程序清单3.4中的代码将会通过持续地调用这个函数来绘制一段动画。但是,你可能会对这个结果感到不满意,因为setInterval()函数和setTimeout()函数根本不知道如何完成动画,而且也不能精确到毫秒。
程序清单3.4 使用setInterval()函数绘制动画


7a5842c880e8a992dd4b373e0a5c412147c46d28

程序清单3.4中的代码每1000/60毫秒调用一次draw()函数,等价于每秒60帧。这个速率是帧速率的一个最优估计,既然是一个估计,它就不是很精确。
我们必须能够预估绘制下一个动画帧的最佳时间,因为setInterval()函数和setTimeout()函数并不知道任何关于动画的事情,因此需要开发人员来确定帧速率。如果浏览器知道什么时候绘制下一个动画帧,而不是依赖于开发人员,就更完美了。
使用setTimeout()和setInterval()有一个更为严重的问题。尽管你向这些函数提供了毫秒级的时间间隔,但是这些函数的精确度达不到毫秒级。事实上,根据HTML指南,为了节约资源,这些方法会慷慨地向你提供所要求的时间间隔。
为了确保动画的平滑度,你不应该使用setTimeout()和setInterval()来完成对时间有苛刻要求的动画,你应该使用requestAnimationFrame()来代替,这将在下一节讨论。
连环画
在讲解动画和电影之前,我们先聊聊“连环画”。假如书的每一页都包含一些图像,这些图像和前一页相比都有微小的变化,当你翻书时,就会产生出运动的假象。连环画最早是因为Cracker Jack(爆米花和坚果混合的甜食)流行起来的,在Cracker Jack食品的包装盒里会包含它作为奖品。
今天我们在视频游戏中实现动画的技术和连环画类似。但它不像一本书包含有限的页数,视频游戏会有一个永不停止的动画帧流,同连环画一样,游戏的动画帧在毫秒级的时间间隔里显示一个静态的图片,随着时间的流逝,这个图片会逐渐改变内容。

对时间要求苛刻的动画,应使用requestAnimationFrame()函数,而不是使用setTime-out()或者setInterval()函数。

3.2.1 requestAnimationFrame()方法
一个名为“Timing Control for Script-based Animations”的W3C说明定义了request-AnimationFrame()窗口对象的方法。不同于setTimeout()和setInterval(),requestAnimation-Frame()是专门用来实现动画的。因此不会存在上面提到的有关setTimeout()和setInterval()的缺点。它也很容易使用,如程序清单3.5所示。
传递给requestAnimationFrame()一个回调函数的引用,当浏览器准备绘制下一个动画帧时,它会回调该回调函数。为了维护动画,回调函数也会调用requestAnimationFrame(),用于在函数绘制下一帧时把自己标识为函数。
程序清单3.5 使用requestAnimationFrame()绘制动画


14420abfa1f729ae8e33dad6f7fdd772a0ef3de6

正如程序清单3.5所示,浏览器会传递给回调函数一个名为now的参数。你或许会对now参数的作用有疑惑。它是代表当前时间的字符串,还是代表自1970年1月1日以来过了多少秒,或者代表其他什么?
但是让人奇怪的是,这个时间没有一个统一的定义。唯一确定的是对于任何浏览器来说,它代表了相同的东西,因此你可以使用它来计算两个动画帧之间的时间间隔,3.4节将对此进行更详细的讲述。
3.2.2 requestAnimationFrame()的polyfill实现
从许多方面来看,HTML5都是开发者的乌托邦。因为有各种免费的专用API可以使用,开发人员使用HTML5实现的应用可以在各种浏览器平台和设备上运行。技术进步得非常快,会持续地增加新技术,并且重新定义已有的功能。
在实现新的技术标准时,不同的浏览器往往会因为浏览器自身固有的特性而采用不同的实现方法。因此浏览器开发商经常会在这个新功能的名字前面加上一个前缀,这样就不会妨碍其他浏览器实现类似的功能;例如,requestAnimationFrame()最早是由Mozilla实现的,称为mozRequestAnimationFrame()。之后其他浏览器厂商也实现了这个功能,如WebKit内核,其实现了webkitRequestAnimationFrame()函数。最后,W3C组织将它标准化为requestAnimationFrame()。
带有前缀的函数以及标准实现的不同支持情况让新功能很难被广泛应用,因此HTML5社区开发了一个名为polyf?ill的机制。polyf?ill机制也可以称为shim机制或者shiv机制,它决定了浏览器支持特定功能的能力。如果浏览器实现了该功能,它们会提供接口;如果没有实现该功能,则提供一个替代解决方案,用于模拟标准功能。
polyf?ills使用简单,但是很难开发。程序清单3.6显示了一个使用polyf?ill实现的request-AnimationFrame()。
程序清单3.6 requestAnimationFrame()的polyfill实现


3c47e4dd6791154576f4b7b9f45da60f6e20e1e6


6b40bf0cb58d2e8646643972daa233692550615b

程序清单3.6所示代码基于polyf?ill机制,在窗口对象中封装了一个名为requestNext-AnimationFrame()的函数。函数名字中的Next把它同默认的名字requestAnimationFrame()区分开来。
polyf?ill机制指向requestNextAnimationFrame()函数或者requestAnimationFrame()函数,又或是浏览器厂商已经实现的功能。如果浏览器不支持任何一个功能,函数将会调用函数setTimeout()来尽可能地模拟requestAnimationFrame()。
polyf?ill机制中几乎所有的复杂操作,包括对两个bug的处理,都在程序清单3.6中代码结尾处的return声明之前完成。第一个bug涉及Chrome 10,它传递了一个未定义的时间值。第二个bug涉及Firefox 4.0,它将帧速率限制在每秒35到40帧之间。
尽管polyf?ill机制中的requestNextAnimationFrame()函数实现很有趣,但你没有必要理解实现过程,你只需要了解如何使用就可以,这将在下一节中讲述。
对未来的规划,使用polyfills机制编程
过去,开发跨平台软件一直是开发人员的共同愿望。polyf?ill机制可以实现这个想法,在更高版本存在时,给你提供接口,不存在时,可以降低版本来完成最基本的功能。

+new Date()

+new Date()是JavaScript中获取当前时间的方法之一。加号将日期强制转换为数字。

requestAnimationFrame()与requestNextAnimationFrame()

这本书中,我们使用前面讨论的requestNextAnimationFrame()的polyf?ill实现,如果浏览器存在默认的requestAnimationFrame()就使用它,如果不存在,polyf?ill机制就会使用备用的解决方案运行。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
markdown 替代品 asciidoc 介绍
AsciiDoc,它的设计初衷就是为了解决写书规模的问题,并且是 O’Reilly 的在线出版平台 Atlas 的推荐语言。经过一番学习,我觉得 Asciidoc 确实很适合电子书制作。 AsciiDoc 相比 Markdown 支持更多的格式,包括而不限于: • 文档属性,设置作者、版本信息等。 • 语法高亮。 • 表格。 • Include 功能,将大文档拆分几个文件。 • 自定义块语法,可扩展性。
9 0
Chrome 插件 User-Agent Switcher 原来是个隐藏木马
Chrome 插件 User-Agent Switcher 原来是个隐藏木马
7 0
JavaScript 各版本介绍和特性
JavaScript 1.1 Netscape Navigator 3.0在1996年8月19发布,是支持JavaScript的浏览器的第二个主要的版本。
11 0
Node.js 安装和入门
什么是 Node? Node(正式名称 Node.js)是一个开源的、跨平台的运行时环境,有了它,开发人员可以使用 JavaScript 创建各种服务器端工具和应用程序。此运行时主要用于浏览器上下文之外(即可以直接运行于计算机或服务器操作系统上)。据此,该环境省略了一些浏览器专用的 JavaScript API,同时添加了对更传统的 OS API(比如 HTTP 库和文件系统库)的支持。
6 0
实战营第三期:MySQL数据库进阶实战
实战营第三期:MySQL数据库进阶实战
8 0
数据库五章其四 ——数据库设计
数据库五章其四 ——数据库设计
4 0
云起第一期学习体会(报告)
云起第一期学习体会(报告)
7 0
牛逼!TCP 粘拆包问题及 Netty 中的解决方案
本文选自 Doocs 开源社区旗下“源码猎人”项目,作者 AmyliaY。
6 0
iOS 调试:通过 Safari/Chrome 调试 WebView
iOS 调试:通过 Safari/Chrome 调试 WebView
6 0
10059
文章
0
问答
来源圈子
更多
+ 订阅
文章排行榜
最热
最新
相关电子书
更多
OceanBase 入门到实战教程
立即下载
阿里云图数据库GDB,加速开启“图智”未来.ppt
立即下载
实时数仓Hologres技术实战一本通2.0版(下)
立即下载