具有角度的HTML5画布drawImage

Gre*_*reg 31 javascript html5 drawimage

我正在尝试动画,<canvas>并且无法确定如何以一定角度绘制图像.期望的效果是像往常一样绘制的一些图像,其中一个图像缓慢旋转.(如果这有任何区别,则此图像不在屏幕的中心).

Jak*_*rek 63

在绘制要旋转的图像之前,需要修改变换矩阵.

假设图像指向HTMLImageElement对象.

var x = canvas.width / 2;
var y = canvas.height / 2;
var width = image.width;
var height = image.height;

context.translate(x, y);
context.rotate(angleInRadians);
context.drawImage(image, -width / 2, -height / 2, width, height);
context.rotate(-angleInRadians);
context.translate(-x, -y);
Run Code Online (Sandbox Code Playgroud)

x,y坐标是画布上图像的中心.

  • 虽然使用save()/ restore()可能看起来更干净,但效率会低得多.引擎必须存储/恢复所有上下文属性,而不仅仅是我们在这里操作的属性.这在敏感的代码路径中很重要. (29认同)
  • 而不是在最后旋转/翻译,你可以在进行转换和绘图之前和之后做一个`context.save()`和`context.restore()`. (4认同)
  • @JakubWieczorek不,引擎可以很容易地在每个上下文属性上保留"脏"标志,并且懒得保存(然后恢复)只有在`save()`和`restore()`之间触及的那些.手动调整这是不成熟的优化. (4认同)
  • -1 使用“translate()”和“rotate()”来恢复变换矩阵是非常糟糕的建议。由于浮点运算的舍入,这不会可靠地将矩阵恢复为其原始值。 (3认同)
  • @JakubWieczorek 你测量过这两种方法的性能吗?如果两个方法调用(其中 `rotate()` 需要调用两个三角函数)比复制整个变换矩阵(48 个字节,如果实现为 6 个 64 位浮点数)更快,我会感到惊讶。 (3认同)

小智 10

有趣的是,第一个解决方案对这么多人都有效,但没有给出我需要的结果。最后我不得不这样做:

ctx.save();
ctx.translate(positionX, positionY);
ctx.rotate(angle);
ctx.translate(-x,-y);
ctx.drawImage(image,0,0);
ctx.restore();
Run Code Online (Sandbox Code Playgroud)

(positionX, positionY)我希望图像所在的画布上的坐标在哪里,是(x, y)我希望图像旋转的图像点。


Yau*_*ume 8

我编写了一个函数(基于Jakub的答案),允许用户根据自定义旋转点中的自定义旋转在X,Y位置绘制图像:

function rotateAndPaintImage ( context, image, angleInRad , positionX, positionY, axisX, axisY ) {
  context.translate( positionX, positionY );
  context.rotate( angleInRad );
  context.drawImage( image, -axisX, -axisY );
  context.rotate( -angleInRad );
  context.translate( -positionX, -positionY );
}
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样调用它:

var TO_RADIANS = Math.PI/180; 
ctx = document.getElementById("canvasDiv").getContext("2d");
var imgSprite = new Image();
imgSprite.src = "img/sprite.png";

// rotate 45º image "imgSprite", based on its rotation axis located at x=20,y=30 and draw it on context "ctx" of the canvas on coordinates x=200,y=100
rotateAndPaintImage ( ctx, imgSprite, 45*TO_RADIANS, 200, 100, 20, 30 );
Run Code Online (Sandbox Code Playgroud)

  • -1 使用“translate()”和“rotate()”来恢复变换矩阵是非常糟糕的建议。由于浮点运算的舍入,这不会可靠地将矩阵恢复为其原始值。 (4认同)