在Canvas上以角度绘制图像,而不旋转Canvas。

10

我正在使用JavaScript中的canvas在HTML 5中绘制一张图片。 我需要以旋转角度绘制它。 我知道可以使用canvas的上下文应用rotate(angle)函数来实现,但是我需要在不旋转canvas本身的情况下进行。

如果可能的话,请提供可能的方法。

4个回答

10

你实际上可以将需要旋转的任何东西绘制到一个离屏画布中,然后将其绘制到主画布中。我从谷歌 IO 演讲中借鉴了以下代码:

rotateAndCache = function(image,angle) {
  var offscreenCanvas = document.createElement('canvas');
  var offscreenCtx = offscreenCanvas.getContext('2d');

  var size = Math.max(image.width, image.height);
  offscreenCanvas.width = size;
  offscreenCanvas.height = size;

  offscreenCtx.translate(size/2, size/2);
  offscreenCtx.rotate(angle + Math.PI/2);
  offscreenCtx.drawImage(image, -(image.width/2), -(image.height/2));

  return offscreenCanvas;
}

然后使用以下方式进行缓存:

rotobj = rotateAndCache(myimg,myangle)

在你的绘图代码中:

mycontext.drawImage(rotobj,x_coord,y_coord)

只有当您拥有一个被旋转一次并随后仅受变换影响的对象时,这才有用。


谢谢PeterT。那几乎符合我所寻找的要求。再次感谢。 - Vinayak
1
@Alexander 实际上我有:http://www.google.com/events/io/2011/sessions/super-browser-2-turbo-hd-remix-introduction-to-html5-game-development.html 视频在这里:http://www.youtube.com/watch?v=yEocRtn_j9s - PeterT
有类似的方法来缩放图片吗? - Kantesh
rotate(angle + Math.PI/2) 中不应该有一个转换错误吗?应该是 rotate(angle * Math.PI/2) - Ain Tohvri
1
@AinTohvri 不是的,'+' 是正确的,它只是用来调整 0 度向右而不是向上的角度。这通常很有用,在这种情况下也是如此,因为它允许更容易地对齐到鼠标指针(使用 atan2 的直接结果)。 - PeterT
显示剩余8条评论

3

当您在画布上应用变换时,您并没有旋转画布。您只是告诉所有要绘制的内容将以特定的方式进行变换。如果您想避免变换影响其他命令,请使用save()restore()方法。它们允许保存和恢复画布的设置。

ctx.save();
ctx.rotate(30);
ctx.drawImage();
ctx.restore();

有没有类似的方法来缩放图像? - Kantesh
是的,使用 scale 而不是 rotate。还有两个参数,水平和垂直缩放因子。 - bjornd

1

我已经点赞了@PeterT的代码片段,非常好用,谢谢!但是为了让它在我的项目中正常工作,我不得不做出三个小改动:

1. 宽度和高度的最大值是不够的:如果你考虑旋转一个正方形,你需要一个直径是正方形对角线的圆形(var diam)。
2. 画布需要被平移回来(或使用保存/恢复)。
3. 对象的x和y坐标必须根据画布大小进行调整。

所以我最终得到:

    rotateAndCache = function(image,angle) {
        var offscreenCanvas = document.createElement('canvas');
        var offscreenCtx = offscreenCanvas.getContext('2d');

        var size = Math.max(image.width, image.height);
        var diam = 2*((size/2)*Math.sqrt(2));                 // needs to be saved
        offscreenCanvas.width = diam;
        offscreenCanvas.height = diam;

        offscreenCtx.translate(diam/2, diam/2);
        offscreenCtx.rotate(angle);
        offscreenCtx.drawImage(image, -(image.width/2), -(image.height/2));
        offscreenCtx.translate(-diam/2, -diam/2);

        return offscreenCanvas;
}


并且调整后的绘制位置(需要保存在rotateAndCache中):
mycontext.drawImage(rotobj,x-(diam-width)/2,y-(diam-height)/2);


如果你想要精确的话,你需要一个直径等于矩形对角线的圆,所以代码应该是 var diam = Math.sqrt(image.width*image.width + image.height * image.height); 但是没错,我理解你的意思。 - PeterT
是的,最大尺寸很令人困惑,我指的是对角线。��码应该这样做(这是一个1-1-√2的直角三角形) - dhc
但这不是一个长度为max(image.width,image.height)的正方形的对角线吗?它可能会比较长于一个具有不等边长的矩形的对角线(至少不会更小,因此不会导致错误)。 - PeterT

0

那是不可能的,而且你可能不需要它。试试这个:

context.save() // Save current state (includes transformations)
context.rotate()
... draw image ...
context.restore() // Restore state

有没有类似的方法来缩放图像? - Kantesh

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