繁体   English   中英

在 HTML5 Canvas 上调整旋转形状的大小

[英]Resize rotated shape on HTML5 Canvas

我想调整旋转形状的大小而不让它飘走。 我知道我需要根据旋转角度调整形状坐标,但我似乎无法弄清楚这样做的公式。

这是我迄今为止设法做的事情( https://jsfiddle.net/9o3vefym/1/

<!DOCTYPE html>
<html>
  <body style="margin: 0">
    <canvas
      id="canvas"
      width="400"
      height="400"
      style="border: 1px solid #d3d3d3"
    ></canvas>
    <script>
      const canvas = document.getElementById("canvas");
      const context = canvas.getContext("2d");
      const rect = {
        x: 100,
        y: 100,
        width: 50,
        height: 50,
        angle: 0
      };
      window.onkeydown = keyDown;

      draw();

      function keyDown(evt) {
        if (evt.key == "ArrowRight") {
          rect.width += 5;
        }
        if (evt.key == "ArrowLeft") {
          rect.x -= 5;
          rect.width += 5;
        }
        if (evt.key == "ArrowUp") {
          rect.y -= 5;
          rect.height += 5;
        }
        if (evt.key == "ArrowDown") {
          rect.height += 5;
        }
        if (evt.key == "a") {
          rect.angle -= (45 * Math.PI) / 180;
        }
        if (evt.key == "s") {
          rect.angle += (45 * Math.PI) / 180;
        }
        draw();
      }

      function draw() {
        context.setTransform(1, 0, 0, 1, 0, 0);
        context.clearRect(0, 0, canvas.width, canvas.height);

        const cx = (rect.x * 2 + rect.width) / 2;
        const cy = (rect.y * 2 + rect.height) / 2;
        context.translate(cx, cy);
        context.rotate(rect.angle);
        context.translate(-cx, -cy);

        context.fillRect(rect.x, rect.y, rect.width, rect.height);
      }
    </script>
  </body>
</html>

如果形状没有旋转,它工作正常,但如果我尝试调整旋转形状的大小,它会崩溃。

例如,如果我通过按“a”或“s”键旋转矩形,然后使用任何箭头键调整它的大小,矩形将“漂移”。 我想要做的是在调整矩形大小时保持矩形静止,因为它在不旋转时会发生。

此外,我正在尝试找到一个不涉及更改draw()的解决方案,因为我无法在代码库中执行此操作,因此我正在尝试解决此问题。

我真的很感激一些帮助。

这在draw()之外是不可修复的。 问题是 draw 方法总是假设矩形的中心是旋转点,但你想要的是能够根据矩形的生长方向移动旋转点。避免漂移的唯一方法更改draw()是始终将矩形保持在同一点的中心。 查看代码片段的注释部分。

您无法在draw()之外修复它的原因是因为在第一行完成了转换重置。 否则,您可以在draw()之前和之后调整变换以适应。

 const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); const rect = { x: 100, y: 100, width: 50, height: 50, angle: 0 }; window.onkeydown = keyDown; draw(); function keyDown(evt) { if (evt.key == "ArrowRight") { //rect.x -= 2.5; rect.width += 5; } if (evt.key == "ArrowLeft") { rect.x -= 5; //2.5; rect.width += 5; } if (evt.key == "ArrowUp") { //rect.y -= 2.5; rect.height += 5; } if (evt.key == "ArrowDown") { rect.y -= 5; //2.5; rect.height += 5; } if (evt.key == "a") { rect.angle -= (45 * Math.PI) / 180; } if (evt.key == "s") { rect.angle += (45 * Math.PI) / 180; } draw(); } function draw() { // The next line is why you can't fix the drift outside of draw(). context.setTransform(1, 0, 0, 1, 0, 0); context.clearRect(0, 0, canvas.width, canvas.height); const cx = (rect.x * 2 + rect.width) / 2; const cy = (rect.y * 2 + rect.height) / 2; context.translate(cx, cy); context.rotate(rect.angle); context.translate(-cx, -cy); context.fillStyle = "#000"; context.fillRect(rect.x, rect.y, rect.width, rect.height); context.fillStyle = "#F00"; context.fillRect(cx, cy, 2, 2); }
 <!DOCTYPE html> <html> <body style="margin: 0"> <canvas id="canvas" width="400" height="400" style="border: 1px solid #d3d3d3" ></canvas> <script> </script> </body> </html>

这是另一个需要在draw()内部进行更改的解决方案的片段。 这个想法是你首先定义cxcy并保持它们固定。

 const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); const rect = { x: 100, y: 100, width: 50, height: 50, angle: 0 }; rect.cx = rect.x + rect.width / 2; rect.cy = rect.y + rect.height / 2; window.onkeydown = keyDown; draw(); function keyDown(evt) { if (evt.key == "ArrowRight") { rect.width += 5; } if (evt.key == "ArrowLeft") { rect.x -= 5; rect.width += 5; } if (evt.key == "ArrowUp") { rect.y -= 5; rect.height += 5; } if (evt.key == "ArrowDown") { rect.height += 5; } if (evt.key == "a") { rect.angle -= (45 * Math.PI) / 180; } if (evt.key == "s") { rect.angle += (45 * Math.PI) / 180; } draw(); } function draw() { context.setTransform(1, 0, 0, 1, 0, 0); context.clearRect(0, 0, canvas.width, canvas.height); context.translate(rect.cx, rect.cy); context.rotate(rect.angle); context.translate(-rect.cx, -rect.cy); context.fillStyle = "#000"; context.fillRect(rect.x, rect.y, rect.width, rect.height); context.fillStyle = "#F00"; context.fillRect(rect.cx, rect.cy, 2, 2); }
 <!DOCTYPE html> <html> <body style="margin: 0"> <canvas id="canvas" width="400" height="400" style="border: 1px solid #d3d3d3" ></canvas> <script> </script> </body> </html>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM