var frame = 0;
var lastUpdateTime = 0;
var acDelta = 0;
var msPerFrame = 100;
function update() {
requestAnimFrame(update);
var delta = Date.now() – lastUpdateTime;
if (acDelta > msPerFrame)
{
acDelta = 0;
redraw();
frame++; if
(frame >= 6) frame = 0;
} else {
acDelta += delta;
}
lastUpdateTime = Date.now();
}
载入后,小猫的移动速度会更合理一些。
()
缩放和旋转当图像渲染后,你还是可以使用这个2D画布来执行各种操作,如旋转和缩放。
例如,把图像缩小一半。你可以通过添加ctx.scale(0.5, 0.5)来达到效果:
function redraw()
{
ctx.fillStyle = ‘#000000′;
ctx.fillRect(0, 0, canvas.width, canvas.height);
if (imageReady)
{
ctx.save();
ctx.scale(0.5,0.5);
ctx.drawImage(img, frame*96, 0, 96, 54,
canvas.width/2 – 48, canvas.height/2 – 48, 96, 54);
ctx.restore();
}
}
()
你会发现我还在缩放命令前添加了ctx.save(),以及在最后添加了ctx.restore()。没有这个,缩放命令就会累积,而可怜的小猫就会很快缩小到看不见(试一下,很有意思)。
使用负值还可以达到颠倒图像的效果。如果你把缩放值从(0.5, 0.5)变成(-1, 1),那么猫图像就会水平翻转,这样它就会往相反的方向跑。注意,这个转变是用翻转起点X位置达到反转图像的效果。
function redraw() {
ctx.fillStyle = ‘#000000′;
ctx.fillRect(0, 0, canvas.width, canvas.height);
if (imageReady) { ctx.save();
ctx.translate(img.width, 0);
ctx.scale(-1, 1);
ctx.drawImage(img, frame*96, 0, 96, 54,
canvas.width/2 – 48, canvas.height/2 – 48, 96, 54);
ctx.restore();
}
}
你可以尝试一下。以下是猫爬墙的动画(其实是竖直旋转了动画):
ctx.rotate( 270*Math.PI/180 );
ctx.drawImage(img, frame*96, 0, 96, 54,
-(canvas.width/2 – 48), (canvas.height/2 – 48), 96, 54);
在这个例子中,通过旋转内容,不只是图像旋转了,连坐标也旋转了,所以drawImage命令通过反转猫绘制的X位置来抵消这个。
()
真是一只天才的猫(不过吸血鬼本来就能爬墙)。
缩放和旋转效果很好。好是好,但它也很慢,会对渲染表现产生重大影响。在制作游戏时,还有另一个技巧——预渲染,可以解决这个问题以及你可能遇到了大量其他渲染表现问题。
预渲染预渲染就是提前处理图像。你只做一次昂贵的渲染操作,然后循环使用已渲染好的结果。
在HTML5中,你必须在分开的不可见画布上绘制,然后不是绘制图像,而是把其他画布绘制在图像的位置上。
以下是预渲染猫的代码例子:
var reverseCanvas = null;
function prerender() {
reverseCanvas = document.createElement(‘canvas’);
reverseCanvas.width = img.width;
reverseCanvas.height = img.height;
var rctx = reverseCanvas.getContext(“2d”);
rctx.save(); rctx.translate(img.width, 0);
rctx.scale(-1, 1);
rctx.drawImage(img, 0, 0);
rctx.restore();
}
注意,画面对象是创建的,不是添加到文件占的,所以它不会显示出来。高度和宽度设置到原来的子画面表格中,然后原图像会使用渲染器的2D环境绘制图像。
为了设置预渲染,你可以从loaded功能中调用它。
function loaded() {
imageReady = true;
prerender();
requestAnimFrame(update);
}
然后当你制作定期重绘制命令时,使用reverseCanvas而不是原来的画布:
function redraw() {
ctx.fillStyle = ‘#000000′;
ctx.fillRect(0, 0, canvas.width, canvas.height);
if (imageReady) {
ctx.save();
ctx.drawImage(reverseCanvas, frame*96, 0, 96, 96,
(canvas.width/2 – 48), (canvas.height/2 – 48), 96, 96);
ctx.restore();
}
}
不幸地是,当我们颠倒图像,动画也会往后播放,所以你必须把动画顺序也颠倒一下:
function update() {
requestAnimFrame(update);
var delta = Date.now() – lastUpdateTime;
if (acDelta > msPerFrame) {
acDelta = 0;
redraw();
frame–;
if (frame < 0) frame = 5;
} else {
acDelta += delta;
}
lastUpdateTime = Date.now();
}
如果有需要,你可以把画面转换成图像,即设置它的来源为使用包含编码图像数据的数据URL。画布有方法可以达到这个效果,所以代码很简单:
newImage = new Image();
newImage.src = reverseCanvas.toDataURL(“image/png”);
另一个有意思的图像操作是使用真正的象素数据。HTML5画布元素把图像数据当作RGBA格式的象素集合来显示。代码如下:
var imageData = ctx.getImageData(0, 0, width, height);
上述代码会返回一个包含宽度、高度和数据成员的ImageData结构。这个数据元素就是一个象素的集合。