Image 在html5画布上旋转单个图像(而不是其他图像)?

Image 在html5画布上旋转单个图像(而不是其他图像)?,image,html,canvas,rotation,Image,Html,Canvas,Rotation,我有一个精灵,我正在html画布上使用普通精灵表布点设置动画。在某些关键事件中,我希望更改精灵的方向(即翻转或旋转180度),而不更改画布上的任何内容(其他精灵) 有人知道怎么做吗?只需通过旋转变换重新绘制精灵即可 画布只是一个屏幕外缓冲区。除非你告诉它,否则它不会被清除,除非你告诉它,否则它不会被改变 在很多不同的情况下,您可能需要重新绘制精灵的区域或其周围。否则,您将获得重影效果,其中旧精灵的一部分在新图形下方仍然可见,或者其他图形变得模糊。原因包括: 你的精灵是部分透明的 你的雪碧是半透

我有一个精灵,我正在html画布上使用普通精灵表布点设置动画。在某些关键事件中,我希望更改精灵的方向(即翻转或旋转180度),而不更改画布上的任何内容(其他精灵)


有人知道怎么做吗?

只需通过旋转变换重新绘制精灵即可

画布只是一个屏幕外缓冲区。除非你告诉它,否则它不会被清除,除非你告诉它,否则它不会被改变

在很多不同的情况下,您可能需要重新绘制精灵的区域或其周围。否则,您将获得重影效果,其中旧精灵的一部分在新图形下方仍然可见,或者其他图形变得模糊。原因包括:

  • 你的精灵是部分透明的
  • 你的雪碧是半透明的
  • 其他的画是在你的精灵上面画的
  • 你的精灵不是长方形的
  • 你所做的翻转不是90度的倍数
所以这可能需要更多的工作,有几种不同的方法可以做到这一点。您可以使用
clip
方法简单地重画整个场景,或者只重画该位置的特定对象


一个完全不同的方向可能是使用其他HTML元素,
img
div
,以及绝对定位和CSS3转换。将场景的渲染委托给浏览器基本上是一个小把戏。

虽然我欣赏Shtêf的回答,但经过一点研究,我发现旋转实际用于显示的画布似乎并不理想。在尝试创建复杂动画(又名think Street Fighter 2 not astroids)时的保存、旋转和恢复操作会导致画布在甚至是Chrome中闪烁

然而,我发现了一个有用的策略。这里的想法是,你实际上创建了两个画布,一个用于你的游戏,另一个是各种各样的后缓冲,用于旋转或缩放你的精灵。基本上是变换backbuffer画布,绘制有问题的图像,然后将其传输到主画布并恢复(或不恢复)backbuffer。以这种方式,你只旋转隐藏的画布,只影响有问题的精灵,而不是整个游戏板

代码如下所示(正在进行中的工作):


这让我省去了很多麻烦,因为我知道如何翻译我的精灵,而不用让我的游戏板上的所有东西到处移动。它的性能似乎也比修改主上下文要好。

所以我的游戏有这个问题;我有用于上、下和左动画的单元格,但没有用于右动画的单元格。所以我需要翻转左边的单元格来画右边的单元格

对于每个精灵,我会在画布上记录它的当前顶部和左侧,以及精灵表中每个单元格的顶部和左侧

我以前看到的答案显示了一个简单的水平翻转,即平移原点和轴的翻转(逆比例),但是这没有考虑到对于精灵,翻转原点会弄乱精灵的注册点(画布上的顶部和左侧)

这个问题表现在精灵被正确镜像,但是它的位置被精灵的宽度关闭。我通过考虑精灵的宽度来解决这个问题。注意我是如何使用CanvasRenderingContext2D.prototype.drawImage和9个参数的,因为我正在从精灵工作表中切片精灵:

// check if we need to flip image (special case for right movement)
if(sprite.translated){
  context.save();
  context.translate(context.canvas.width, 0);
  context.scale(-1, 1);
  context.drawImage(sprite.sheet,
    cell.left,
    cell.top,
    sprite.width,
    sprite.height,
    // secret sauce: change the destination's X registration point
    context.canvas.width - sprite.left - sprite.width,
    sprite.top,
    sprite.width, sprite.height);
  context.restore();
} else {
  // Assumes cells are all the same width and height, set in sprite
  context.drawImage(sprite.sheet, cell.left, cell.top, sprite.width,
  sprite.height, sprite.left, sprite.top, sprite.width, sprite.height);
}
注意:我也可以在translate中进行计算,因为它旨在简化其他地方的计算。

为什么不使用save()和restore

ctx.save(); // save current state
ctx.rotate(Math.PI); // rotate
ctx.drawImage(link,x,y,20,20); // draws a chain link or dagger
ctx.restore(); // restore original states (no rotation etc)

我想可能是我误解了。我认为rotate(从我看到的示例中)似乎可以旋转画布上的所有内容。这种方法是否适用于单个图像而不旋转其他图像?我试试。
rotate
更改转换矩阵,它是画布状态的一部分。旋转之后的一切都会受到旋转的影响。您可以使用
save
restore
在旋转前创建画布状态的快照,然后在绘制完成后恢复该快照。你通常在绘图操作中像块一样应用
保存
恢复
。嗯,我考虑过这一点,在游戏中这样做似乎是错误的。将旋转应用于画布而不是图像本身的想法似乎非常笨拙。例如,对于每个改变方向的精灵,我必须保存、旋转、绘制和恢复。也许我遗漏了什么?在actionscript中,可以创建一个矩阵,将其应用于位图并完成。例如:myBitmap=BitmapData.loadBitmap(“测试”)//翻转垂直矩阵flipVerticalMatrix=new matrix()flipVerticalMatrix.scale(1,-1)flipVerticalMatrix.translate(0,myBitmap.height)//翻转水平矩阵flipHorizontalMatrix=new matrix()flipHorizontalMatrix.scale(-1,1)flipHorizontalMatrix.translate(myBitmap.width,0)flippedBitmap=新位图数据(myBitmap.width,myBitmap.height,false,0x FFCC00)flippedBitmap.draw(myBitmap,flipHorizontalMatrix)this.attachBitmap(flippedBitmap,1)免责声明:我对游戏开发+html5完全是个业余爱好者-因此,请随时评论或纠正我,我将很高兴地更改此答案。根据我的经验,转换不会导致闪烁。除此之外,对整个画布应用转换可能看起来很大,但它实际上只是一个状态变量,一小部分数字。我想无论什么东西能让你的船漂浮可能重复的
ctx.save(); // save current state
ctx.rotate(Math.PI); // rotate
ctx.drawImage(link,x,y,20,20); // draws a chain link or dagger
ctx.restore(); // restore original states (no rotation etc)