【问题标题】:Rotate canvas keyevent旋转画布按键事件
【发布时间】:2018-08-20 17:10:21
【问题描述】:

如何使用 keydown 事件旋转画布三角形?

例如,如果我创建一个这样的三角形:

function drawTriangle(){

    ctx.save();
    ctx.translate(x,y)
    ctx.beginPath();
    ctx.moveTo(0, 0);
    ctx.lineTo(-50, 50);
    ctx.lineTo(50, 50);
    ctx.closePath();
    ctx.stroke();
    ctx.restore();

我在哪里编码旋转? keydown 事件函数内部?

就像,当我按下右箭头时,三角形应该向右,当按下左三角形时,向上和向下相同。

谢谢。

【问题讨论】:

  • 这完全取决于您计划如何轮换它。如果你只是在旋转三角形,如果你在旋转整个屏幕,你打算旋转的位置等等。
  • 只旋转三角形,就像我按右箭头键,三角形向右移动,如果我按左键,三角形向左移动。 Down 和 Up 一样。

标签: javascript events canvas


【解决方案1】:

诀窍是首先将画布平移到您希望旋转的点,执行旋转,然后撤消平移。以下将围绕三角形顶部旋转(您会看到我使用xy 作为旋转的原点)

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
let x = 50;
let y = 50;
let angle = 0;

function drawTriangle() {
  ctx.save();

  // Move to the point you wish to rotate around
  ctx.translate(x, y);
  // Rotate to the desired angle
  ctx.rotate(angle * Math.PI / 180);
  // Undo the initial translation
  ctx.translate(-x, -y);

  ctx.translate(x, y);
  ctx.beginPath();
  ctx.moveTo(0, 0);
  ctx.lineTo(-50, 50);
  ctx.lineTo(50, 50);
  ctx.closePath();
  ctx.stroke();
  ctx.restore();
}

document.addEventListener('keydown', (e) => {
  const delta = 2;
  // Rotate the triangle with the left and right arrow keys
  if (e.key === 'ArrowLeft') {
    angle -= delta;
  } else if (e.key === 'ArrowRight') {
    angle += delta;
  }

  // Move around the triangle with wasd
  if (e.key === 'a') {
    x -= delta;
  } else if (e.key === 'd') {
    x += delta;
  } else if (e.key === 'w') {
    y -= delta;
  } else if (e.key === 's') {
    y += delta;
  }

  // Keep the angle between 0 and 360
  if (angle < 0) {
    angle += 360;
  }
  angle = (angle % 360);

  // Make sure to clear the canvas so we don't get a bunch
  // of triangles drawn over each other
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  drawTriangle();
});

drawTriangle();
body {
  background: #000;
}

canvas {
  background: #FFF;
}
&lt;canvas width="320" height="240"&gt;&lt;/canvas&gt;

只是为了好玩,我写了一个控制更流畅的版本。

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
let x = 50;
let y = 50;
const width = 100;
const height = 50;
let angle = 0;

function drawTriangle() {
  ctx.save();

  // Move to the point you wish to rotate around
  // Go to the center of the triangle
  ctx.translate(x, y + height / 2);
  // Rotate to the desired angle
  ctx.rotate(angle * Math.PI / 180);
  // Undo the initial translation
  ctx.translate(-x, -y - height / 2);

  ctx.translate(x, y);
  ctx.beginPath();
  ctx.moveTo(0, 0);
  ctx.lineTo(-width / 2, height);
  ctx.lineTo(width / 2, height);
  ctx.closePath();
  ctx.stroke();
  ctx.restore();
}

const keyMap = {};
document.addEventListener('keydown', e => {
  keyMap[e.key] = true;
});

document.addEventListener('keyup', e => {
  keyMap[e.key] = false;
});

function updatePosition(deltaTime) {
  const pixelsPerSecond = 50;
  const delta = pixelsPerSecond * deltaTime;
  
  if (keyMap.a) {
    x -= delta;
  }
  if (keyMap.d) {
    x += delta;
  }
  if (keyMap.w) {
    y -= delta;
  }
  if (keyMap.s) {
    y += delta;
  }
  
  // Prevent if from going off screen
  const leftSide = x - width / 2;
  const rightSide = x + width / 2;
  const topSide = y;
  const bottomSide = y + height;
  
  if (leftSide < 0) {
    x = width / 2;
  }
  if (rightSide > canvas.width) {
    x = canvas.width - width / 2;
  }
  if (topSide < 0) {
    y = 0;
  }
  if (bottomSide > canvas.height) {
    y = canvas.height - height;
  }
}

function updateRotation(deltaTime) {
  const degreesPerSecond = 45;
  const delta = degreesPerSecond * deltaTime;
  
  if (keyMap.ArrowLeft) {
    angle -= delta;
  }
  if (keyMap.ArrowRight) {
    angle += delta;
  }

  // Keep the angle between 0 and 360
  if (angle < 0) {
    angle += 360;
  }
  angle = (angle % 360);
}

let prevTime = new Date();
function update() {
  let now = new Date();
  let deltaTime = (now - prevTime) / 1000;
  
  updatePosition(deltaTime);
  updateRotation(deltaTime);
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  drawTriangle();
  prevTime = now;
  requestAnimationFrame(update);
}
requestAnimationFrame(update);
body {
  background: #000;
}

canvas {
  background: #FFF;
}
&lt;canvas width="320" height="240"&gt;&lt;/canvas&gt;

【讨论】:

  • 谢谢!在您的第一个答案中,我按下箭头后按下的任何键都会旋转三角形。如何移动三角形而不是旋转?
  • @AndersonTrugilio 按 A 向左移动,D 向右移动,W 向上移动 D 向下移动
  • 嘿,迈克,有办法限制画布内的移动吗?避免三角形离开画布?
  • 当然,无论何时更改xy,只要确保它们不超过特定值即可。例如,如果x 曾经低于 50,则将其设置为 50。如果 y 曾经低于 0,则将其设置为 0。其他边的想法相同。您必须使用画布的大小作为参考点。
  • 我在“只是为了好玩”部分添加了一些代码来执行此操作。当三角形旋转时,它不能确保它保持在该区域内。这需要一些超出此问题范围的数学运算。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-11
  • 2016-07-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多