【问题标题】:Rotating a sprite in a canvas在画布中旋转精灵
【发布时间】:2020-01-12 21:04:40
【问题描述】:

我在一张图像中有多个精灵,我想将单个精灵绘制到画布上。我无法让它们旋转。

当我尝试旋转一个精灵时,它似乎永远不会围绕它应该在的点旋转。

我正在使用以下功能。角度是在加载时设置的。

Sprite.prototype.draw = function (ctx, x ,y) {
    if (this.angle == 0) {
        ctx.drawImage(this.img, this.x, this.y, this.width, this.height, x, y, this.width, this.height);
    }
    else {
        ctx.save();
        ctx.translate(x, y);
        ctx.rotate(this.angle * this._TORADIANS);
        ctx.drawImage(this.img, this.x, this.y, this.width, this.height, x, y, this.width, this.height);
        ctx.restore();
    }
}

我浏览了几个教程,但在这种情况下似乎没有任何效果。

【问题讨论】:

  • 是围绕左上角而不是围绕图像中心旋转的问题吗?如果您可以发布您正在做的事情的简化 JSFiddle,那将有所帮助。否则尝试在rotate 之前添加ctx.translate(this.img.width/2,this.img.height/2);,然后在rotate 之后添加ctx.translate(-this.img.width/2,-this.img.height/2);,这样可以解决您的问题吗?
  • @Jared 是的,也不是。我也必须正确绘制图像。

标签: javascript html canvas graphics


【解决方案1】:

首先将上下文转换为x, y 加上图像尺寸的一半,以便上下文原点位于图像所需位置的中心:

ctx.translate(x + this.width / 2, y + this.height / 2);

将上下文旋转所需的度数:

ctx.rotate(this.angle * Math.PI / 180);

绘制图像,将其尺寸偏移一半以说明原点的位置:

ctx.drawImage(this.img, this.x, this.y, this.width, this.height,
                        -this.width / 2, -this.height / 2, this.width, this.height);

现在撤消旋转和平移:

ctx.rotate(-this.angle * Math.PI / 180);
ctx.translate(-x - this.width / 2, -y - this.height / 2);

在您的情况下,您可以更改Sprite.draw(),如下所示。

Sprite.prototype.draw = function (ctx, x, y) {
    ctx.save();
    ctx.translate(x + this.width / 2, y + this.height / 2);
    ctx.rotate(this.angle * Math.PI / 180);
    ctx.drawImage(this.img, this.x, this.y, this.width, this.height,
                            -this.width / 2, -this.height / 2, this.width, this.height);
    ctx.restore();
};

下面的 sn-p 概括地演示了这种方法。

window.onload = function () {
  var width = 600,
      height = 600,
      canvas = document.getElementsByTagName('canvas')[0],
      context = canvas.getContext('2d');
  canvas.width = width;
  canvas.height = height;
  var image = new Image();
  image.src = 'https://cdn.sstatic.net/Sites/stackoverflow/img/apple-touch-icon.png?v=c78bd457575a';
  function draw(x, y, degrees) {
    context.translate(x + image.width / 2, y + image.height / 2);
    context.rotate(degrees * Math.PI / 180);
    context.drawImage(image, 0, 0, image.width, image.height,
        -image.width / 2, -image.height / 2, image.width, image.height);
    context.rotate(-degrees * Math.PI / 180);
    context.translate(-x - image.width / 2, -y - image.height / 2);
  }
  image.onload = function () {
    var degrees = 0;
    function loop() {
      degrees = (degrees + 1) % 360;
      context.fillRect(0, 0, canvas.width, canvas.height);
      draw(0, 0, degrees);
      window.requestAnimationFrame(loop);
    };
    window.requestAnimationFrame(loop);
  };
};
canvas {
  border: 2px solid #ccc;
}
<canvas></canvas>

【讨论】:

  • 非常感谢您的深入回答!仔细想了想,觉得有点意思了。将原点移动到正在绘制的对象的 X 和 Y 位置,然后进行绘制。我认为这就是人们对代码的困惑。非常感谢!
【解决方案2】:

如果你围绕 x,y 旋转,那么你的代码应该如下所示:

ctx.translate(x, y);
ctx.rotate(this.angle * this._TORADIANS);
ctx.translate(-x, -y); // this part is missed in your case
ctx.drawImage(this.img, this.x, this.y, this.width, this.height, x, y, this.width, this.height);

【讨论】:

  • 当唯一的区别是第二次翻译时,我真的不明白你的代码是如何工作的。但话又说回来,我可以看到它会如何。我的意思是您需要重新聚焦原点为 (0, 0) 的位置,但它是否与图像的 X 和 Y 位置相反?这有点让我失望。但这不是ctx.save();ctx.restore() 的用途吗?不过谢谢。 +1
猜你喜欢
  • 1970-01-01
  • 2011-12-16
  • 2013-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-23
  • 1970-01-01
相关资源
最近更新 更多