最近研究了一下出来了很久的 html5, 总结了一下, 准备来个系列, 文中也许有很多问题, 欢迎大家指正.
Canvas 介绍
canvas 用于在网页中绘制图形的一个元素, 具体内容请查看 -> HTML5 Canvas http://www.w3school.com.cn/html5/html_5_canvas.asp
这里说些 w3school 中没有的.
立即模式
canvas 元素是立即模式的图形系统, 意味着当你提出要求时, 他会立即绘制, 然后立即忘记(绘制完成一个对象, 就会销毁这个对象). 其它的图形系统(例如: SVG), 使用了保留模式的图形系统, 就是说绘制时他们会保留一系列将要绘制的对象. 正因未 Canvas 不需要维护这一系列对象, 所以 Canvas 的运行速度要快很多.
双缓存机制
在上面, 我们提到了立即模式, 但这里的 "立即绘制" 并不是大家所谓的立即, 此处需要进一步说明.
在浏览器调用我们定义的绘制方法 (假设这个方法是 DrawGame) 绘制当前动画帧时, Canvas 元素并不是立即绘制出你指定的内容. 相反, 它会创建另一个 Canvas 元素(我们叫它 Canvas2), 所有的绘制实际上都在 Canvas2 中进行. 当 DrawGame 方法返回时, 浏览器会通过一个图形操作, 复制 Canvas2 内容到屏幕上, 我们将这种技术称为双缓存技术, 双缓存技术让动画的实现变得平滑.
坐标系统(translate)
translate(x,y)这是 Canvas 元素的一个方法, 游戏的背景移动, 大多通过该方法来实现. 游戏中, 我们不会通过频繁对大量元素进行坐标计算来实现对象的滚动, 因为这样的计算不仅消耗计算机性能, 还增加了代码的维护难度.
注意: 为了不影响后续的绘制, 在使用 translate(x,y)修改坐标系统后, 需要再次调用 translate(-x,-y)来恢复坐标系统.
具体内容请查看 -> HTML5 canvas translate() http://www.w3school.com.cn/html5/canvas_translate.asp
创建 Canvas 镜像和恢复 Canvas
在进行动画绘制时, 我们会经常的对 Canvas 元素的绘图环境 (context) 进行修改, 例如 strokeStyle,lineWidth 等. 这些修改操作都是永久的, 也就意味着对他们的修改将会影响接下来任何你在 Canvas 元素的图形操作. 那么如何让这些操作只是临时有效呢? 这里我们可以使用 save()和 restore()方法对当前 Canvas 元素的绘图环境状态创建镜像和恢复. 任何写在这两个方法间的环境属性修改, 在执行 restore 后, 都会恢复成 save 时的状态.
注意: save()和 restore()需要成对出现, 也就是有 save, 就要有 restore.
实现平滑的 HTML5 动画
所谓的动画, 说白了就是一张一张的图片不断的连续更换. 所以, 通过编程实现动画也就是不断的通过替换图片, 来达到动画的效果.
但是, 这种不断地替换, 当然不能使用死循环 while(true)来实现, 传统的方法是使用 setTimeout()和 setInterval()方法, 这两个方法虽然都提供了毫秒级的精确度, 但实际上, 却达不到毫秒级(参考此处: setTimeout 精度测试 https://yq.aliyun.com/ziliao/64850 ,setInterval 精度测试 https://blog.csdn.net/SunshinePengChao/article/details/44617143 ). 所以为了保证动画的平滑度, 我们不应该继续使用 setTimeout 和 setInterval 方法来实现对时间有着苛刻要求的动画, 用什么来代替? 我们在下一节讲到.
requestAnimationFrame()方法
在 w3c 中的 Timing Control for Script-based Animations(参考此处 -> w3c-Script-based Animations https://www.w3.org/TR/animation-timing/ )说明中, 定义了一个 requestAnimationFrame()窗口对象的方法. 不同于 setTimeout 和 setInterval 方法, requestAnimationFrame 是专门用来实现动画的, 它使用浏览器的时间间隔进行绘制, 不会掉帧.
这里需要注意的是, requestAnimationFrame 方法在窗体没激活或者页签不可见的时候, 动画会暂停.
- function animate(now)
- {
- DrawGame(now);
- requestAnimationFrame(animate);
- }
- ...
- requestAnimationFrame(animate);
- var speed = 50;
- var lastAnimationTime = new Date();
- var offsetX = 0;
- function SetBackgroundOffsetX(now)
- {
- offsetX += speed * (now - lastAnimationTime)/1000
- ...
- // 如果一直加下去, 背景会慢慢移出屏幕, 下面的代码自己写吧
- }
来源: https://www.cnblogs.com/zhuxiaoxiao/p/9551697.html