HTML画布:如何绘制翻转/镜像图像?

45

我正在尝试在HTML画布上绘制图像时翻转/镜像它;我找到了一个游戏教程,其中显示了每个角色必须面对的每个方向的精灵表,但这似乎不太对。特别是因为每一帧的大小都不同。

什么是实现此目标的最佳技术?

我尝试在我的画布上调用setScale(-1, 1);,但没有成功。也许那并不是适合这个问题的方法。

谢谢


可能是在canvas中翻转精灵的重复问题。 - Damjan Pavlica
4个回答

39
  1. 在绘制图像之前,您可以通过使用myContext.scale(-1,1)将上下文进行变换,不过这样会降低游戏的速度。

  2. 更好的做法是使用一个独立的、镜像的精灵来代替。


1
好的,我只是担心内存使用情况,但移动设备上的CPU可用性可能更加稀缺。我会按照你建议的方式去做。感谢你的建议! - Jem
4
好的,不要只听我的话。对其进行分析,确保我对你的特定用法没有错误。 :) - Phrogz
1
同意,只需创建一个具有两个独立面的图像精灵就能极大地提高速度。 - Ash Blue
我只是记得,许多GBA游戏的精灵表只有对象的一半,它会绘制原始部分和翻转的另一部分来形成对称的对象,比如树或路灯。只是说一下... - Daniel Cheung
4
思考优化的上下文总是值得的。 在Game Boy或Game Boy Advance游戏中,开发者的内存和存储空间极为有限。今天,您不太可能遇到大小问题。 但是,您仍然可以将其作为优化的重点。如果您想进行练习,为什么不创建一个只包含紧密打包的必要元素的小精灵图表,然后在开始游戏之前将面向不同方向的精灵的版本写入内存。 这样做可以节省速度和内存,但会增加加载时的时间成本。 - Chris Kinniburgh
5
实际上,这不会影响性能。2D画布上下文使用变换矩阵来应用缩放等操作到渲染的顶点上。无论是否调用缩放函数,变换矩阵都是活动的,因此应用缩放不会改变渲染速度。 - LAX1DUDE

32

你需要设置画布的比例,并且反转宽度。

drawToCanvas : function(v, context, width, height){
    context.save();
    context.scale(-1, 1);
    context.drawImage(v, 0, 0, width*-1, height);
    context.restore();
}

可能会存在一些性能问题,但对我来说这不是问题。


3
请注意,变量canvas应该是通过调用canvasElem.getContext("2d")获取的上下文。 - randominstanceOfLivingThing
"...以及将宽度反转。" 这就是我之前缺失的部分... - Ofir G
只在其他操作系统上运行,但不适用于IOS。 - Janusz Slota
参数 v 是什么? - yenren
@Envayo "v" 是要绘制的图像。 - Przemysław Niemiec

14

如果您只是水平翻转它,它将超出边界...因此使用translate来调整其位置:

ctx.translate(canvas.width, 0);
ctx.scale(-1, 1);
ctx.drawImage(img, 0, 0);

如果您想要更短的代码,可以删除translate并将图像大小作为第二个参数的负偏移量在drawImage(x坐标)中使用:

ctx.scale(-1, 1);
ctx.drawImage(img, canvas.width * -1, 0);
如果你想要在之后恢复上下文,请在所有内容前后添加save/restore
ctx.save();
ctx.scale(-1, 1);
ctx.drawImage(img, canvas.width * -1, 0);
ctx.restore();

最简单的方法 - Nick Chan Abdullah
如何恢复上下文?它每隔一次就被反转了。 - Faiyaz Md Abdul
在进行上下文状态更改前,请使用context.save(),并在之后使用context.restore()以恢复先前的上下文状态。 - L777

4

创建反射时,您不需要重新绘制整个图像。一个原始的反射只显示图像的底部部分。这样你只需要重新绘制图像的一小部分,从而提供更好的性能,并且你不需要创建线性渐变来隐藏图像的下部(因为你从未绘制过它)。

 var img = new Image();
 img.src = "//vignette2.wikia.nocookie.net/tomandjerryfan/images/9/99/Jerry_Mouse.jpg/revision/latest?cb=20110522075610";
 img.onload = function() {
   var thumbWidth = 250;
   var REFLECTION_HEIGHT = 50;
   var c = document.getElementById("output");
   var ctx = c.getContext("2d");
   var x = 1;
   var y = 1;

 //draw the original image
   ctx.drawImage(img, x, y, thumbWidth, thumbWidth);
 ctx.save();
 //translate to a point from where we want to redraw the new image
   ctx.translate(0, y + thumbWidth + REFLECTION_HEIGHT + 10);
   ctx.scale(1, -1);
   ctx.globalAlpha = 0.25;
   
   //redraw only bottom part of the image
   //g.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
   ctx.drawImage(img, 0, img.height - REFLECTION_HEIGHT, img.width, REFLECTION_HEIGHT, x, y, thumbWidth, REFLECTION_HEIGHT);

   // Revert transform and scale
  ctx.restore();

 };
 body {
   background-color: #FFF;
   text-align: center;
   padding-top: 10px;
 }
<canvas id="output" width="500" height="500"></canvas>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接