让绘图留在 canvas

getting the drawing to stay on canvas

我在 canvas 上画了一个图,并用按钮将其上下左右移动。但是我在考虑如何让绘图不通过 canvas 的边界时遇到问题,如果我点击方向按钮太多的话。我的 canvas 是 500 x 500。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

function drawObject(ctx, x, y) {
ctx.save();
ctx.beginPath(); //Head of ship
ctx.translate(x, y);
ctx.lineTo(0, 0); //starting point
ctx.lineTo(0, 10); // left of head
ctx.lineTo(15, 20); //connecting left to bottom
ctx.lineTo(50, 20); // bottom of head
ctx.lineTo(65, 10); // connecting bottom to right
ctx.lineTo(65, 0); //line on far right 
ctx.lineTo(50, -10); //top of head
ctx.lineTo(15, -10); //connecting top to left
ctx.lineTo(0, 0);
ctx.stroke();
}
drawObject(ctx, 200, 225);

function up() {
var canvas2 = document.getElementById("myCanvas");
ctx.beginPath(); //Head of ship
ctx.clearRect(-10, -15, 500, 500);
ctx.translate(0, -40);
ctx.lineTo(0, 0); //starting point
ctx.lineTo(0, 10); // left of head
ctx.lineTo(15, 20); //connecting left to bottom
ctx.lineTo(50, 20); // bottom of head
ctx.lineTo(65, 10); // connecting bottom to right
ctx.lineTo(65, 0); //line on far right 
ctx.lineTo(50, -10); //top of head
ctx.lineTo(15, -10); //connecting top to left
ctx.lineTo(0, 0);
ctx.stroke();
}

function right() {
var canvas3 = document.getElementById("myCanvas");
ctx.beginPath();
ctx.clearRect(-10, -15, 500, 500);
ctx.translate(5, 0);
ctx.lineTo(0, 0); //starting point
ctx.lineTo(0, 10); // left of head
ctx.lineTo(15, 20); //connecting left to bottom
ctx.lineTo(50, 20); // bottom of head
ctx.lineTo(65, 10); // connecting bottom to right
ctx.lineTo(65, 0); //line on far right 
ctx.lineTo(50, -10); //top of head
ctx.lineTo(15, -10); //connecting top to left
ctx.lineTo(0, 0);
ctx.stroke();
}

function down() {
var canvas4 = document.getElementById("myCanvas");
ctx.beginPath();
ctx.clearRect(-10, -15, 500, 500);
ctx.translate(0, 5);
ctx.lineTo(0, 0); //starting point
ctx.lineTo(0, 10); // left of head
ctx.lineTo(15, 20); //connecting left to bottom
ctx.lineTo(50, 20); // bottom of head
ctx.lineTo(65, 10); // connecting bottom to right
ctx.lineTo(65, 0); //line on far right 
ctx.lineTo(50, -10); //top of head
ctx.lineTo(15, -10); //connecting top to left
ctx.lineTo(0, 0);
ctx.stroke();
}

function left() {
var canvas5 = document.getElementById("myCanvas");
ctx.beginPath();
ctx.clearRect(-10, -15, 500, 500);
ctx.translate(-5, 0);
ctx.lineTo(0, 0); //starting point
ctx.lineTo(0, 10); // left of head
ctx.lineTo(15, 20); //connecting left to bottom
ctx.lineTo(50, 20); // bottom of head
ctx.lineTo(65, 10); // connecting bottom to right
ctx.lineTo(65, 0); //line on far right 
ctx.lineTo(50, -10); //top of head
ctx.lineTo(15, -10); //connecting top to left
ctx.lineTo(0, 0);
ctx.stroke();
}

function reset() {
var canvas5 = document.getElementById("myCanvas");
ctx.beginPath();
ctx.clearRect(-10, -15, 500, 500);
ctx.restore();
ctx.save();
ctx.translate(200, 225);
ctx.lineTo(0, 0); //starting point
ctx.lineTo(0, 10); // left of head
ctx.lineTo(15, 20); //connecting left to bottom
ctx.lineTo(50, 20); // bottom of head
ctx.lineTo(65, 10); // connecting bottom to right
ctx.lineTo(65, 0); //line on far right 
ctx.lineTo(50, -10); //top of head
ctx.lineTo(15, -10); //connecting top to left
ctx.lineTo(0, 0);
ctx.stroke();
}

如果你想阻止它越过边界,你需要得到一些随着翻译而改变的x,y变量。

例如,只要有 translate( 0, 5 ),就应该在它前面加上 x += 0; y += 5。这样你就可以检查 xy 是否在边界之外,并防止在翻译之前发生任何事情:

function left(){
    ...
    if( x - 5 <= 0 )
        return false
    x -= 5;
    // having y += 0 is redundant, but you can add it for readability purposes
    translate( -5, 0 )
    ...
}

对于其余的方向函数,您需要检查 if 语句中的所有边界:

向上:y - 5 <= 0

左:x - 5 <= 0

向下:y + 5 >= canvas5.height

右:x + 5 >= canvas5.width

您必须在某些变量中保持当前位置(例如 xy)。 然后,不是使用 translate 增加当前变换矩阵,而是使用 setTransform 方法。这将使我们能够避免经常使用不当的 save 方法,并在每次绘制新图时轻松清除 canvas。

那么,你已经有了drawObject方法,就用吧

为了避免撞墙,您只需要在修改 xy 值时检查您是否超出范围(请注意,您还必须考虑执行此检查时的图纸尺寸)

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var defaultX, defaultY; // used in the reset function
var x = defaultX = 200;
var y = defaultY = 125;

function drawObject(ctx, x, y) {
  // reset the current transform so we can clear the canvas
  ctx.setTransform(1, 0, 0, 1, 0, 0);
  ctx.clearRect(0, 0, canvas.width, canvas.height)
  // set the current transform to our actual position
  ctx.setTransform(1, 0, 0, 1, x, y);
  // draw our ship
  ctx.beginPath(); //Head of ship
  ctx.lineTo(0, 0); //starting point
  ctx.lineTo(0, 10); // left of head
  ctx.lineTo(15, 20); //connecting left to bottom
  ctx.lineTo(50, 20); // bottom of head
  ctx.lineTo(65, 10); // connecting bottom to right
  ctx.lineTo(65, 0); //line on far right 
  ctx.lineTo(50, -10); //top of head
  ctx.lineTo(15, -10); //connecting top to left
  ctx.lineTo(0, 0);
  ctx.stroke();
}
drawObject(ctx, x, y);

function up() {
  y -= 5;
  // we gone too far, stop it.
  // -10 is your ship top position
  if (y < 10) {
    y = 10;
  }
  drawObject(ctx, x, y);
}

function right() {
  x += 5;
  // 65 is your ship width
  if (x > canvas.width - 65) {
    x = canvas.width - 65;
  }
  drawObject(ctx, x, y);

}

function down() {
  y += 5;
  // 20 is your ship height
  if (y > canvas.height - 20) {
    y = canvas.height - 20;
  }
  drawObject(ctx, x, y);
}

function left() {
  x -= 5;
  if (x < 0) {
    x = 0;
  }
  drawObject(ctx, x, y);

}

function reset() {
    x = defaultX;
    y = defaultY;
    drawObject(ctx, x, y);
  }
  // replacing your buttons with key events (arrows)
window.onkeydown = function(event) {
  switch (event.keyCode) {
    // left
    case 37:
      event.preventDefault();
      left();
      break;

      // up
    case 38:
      event.preventDefault();
      up();
      break;

      // right
    case 39:
      event.preventDefault();
      right();
      break;

      //down
    case 40:
      event.preventDefault();
      down();
      break;
  }
}
document.getElementById('reset').onclick = reset;
button {
  vertical-align: top;
}
canvas {
  border: 1px solid;
}
<canvas id="myCanvas" width="400" height="200"></canvas>
<button id="reset">
  reset
</button>