如何在画布上绘制并使另一个对象在移动时不在同一个画布上绘制

时间:2021-05-21 17:43:40

标签: javascript css animation canvas

我有一个蓝色圆圈,它围绕红色圆圈旋转,只要按下按钮,它就会在画布上向一个方向连续移动。

  • 现在我想在按下按钮时移动的红色圆圈绘制(跟踪其路径)。

问题:

  • 当我尝试通过不使用 clearRect(0,0, canvas.width, canvas.height); 在画布上绘图时,蓝色圆圈也开始在我不需要的移动时在画布上绘图。

是否可以在同一个画布上用一个圆绘制而不用另一个圆绘制?

const canvas = document.getElementById('canvas1');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let positionX = 100;
let positionY = 100;
let X = 50;
let Y = 50;
let angle = 0;
let mouseButtonDown = false;

document.addEventListener('mousedown', () => mouseButtonDown = true);
document.addEventListener('mouseup', () => mouseButtonDown = false);

function circle(){
    ctx.fillStyle = 'red';
    ctx.beginPath();
    ctx.arc(X, Y, 20, 0, Math.PI*2);
    ctx.closePath();
    ctx.fill();
}
function direction(){
    ctx.fillStyle = 'blue';
    ctx.beginPath();
    ctx.arc(positionX + X, positionY + Y, 10, 0, Math.PI*2);
    ctx.closePath();
    positionX = 35 * Math.sin(angle);
    positionY = 35 * Math.cos(angle);
    ctx.fill();   
}
function animate(){
    if (mouseButtonDown) {
        X += positionX / 10;
        Y += positionY / 10;
    } else {
        angle += 0.1;
    }
    ctx.clearRect(0,0, canvas.width, canvas.height);
    circle();
    direction();
    requestAnimationFrame(animate);   
}
animate();
#canvas1{
    position: absolute;
    top:0;
    left: 0;
    width: 100%;
    height: 100%;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Canvas basics</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <canvas id="canvas1"></canvas>
    
    <script src="script.js"></script>
</body>
</html>

1 个答案:

答案 0 :(得分:2)

我们可以引入一个新变量:
let history = [{X,Y}]
在那里我们可以在移动时保持红色圆圈的位置,并且我们保持代码中的其他所有内容相同,我们仍然使用 clearRect 清除然后重绘所有元素。

在我的示例代码中,我将项目推送到 mouseup 上的历史记录,这意味着在移动完成之前不会显示历史记录,但您可以使用它看看其他事件是否有更好的体验...与从历史中得出的一样,我正在绘制一条虚线,但它可以是其他任何东西。

我唯一改变的是角度 angle += 0.05; 对我来说有点快。

我下面的示例代码将绘制如下内容:

const canvas = document.getElementById('canvas1');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let positionX = 100
let positionY = 100
let X = canvas.width / 2;
let Y = canvas.height / 2;
let angle = 0;
let mouseButtonDown = false;
let history = [{ X, Y }]

document.addEventListener('mousedown', mousedown);
document.addEventListener('mouseup', mouseup);

function mousedown() {
  mouseButtonDown = true
}

function mouseup() {
  mouseButtonDown = false
  history.push({ X, Y })
}

function drawHistory() {
  // draw the lines for history
  ctx.beginPath();
  ctx.strokeStyle = 'black';
  ctx.setLineDash([5, 5]);
  ctx.moveTo(history[0].X, history[0].Y)
  for (let i = 1; i < history.length; i++) {
    ctx.lineTo(history[i].X, history[i].Y)
  }
  ctx.stroke();
  ctx.closePath();
  
  // draw line for current movement
  ctx.beginPath();
  ctx.strokeStyle = 'red';
  ctx.setLineDash([10, 2]);
  ctx.moveTo(history[history.length-1].X, history[history.length-1].Y)
  ctx.lineTo(X, Y)
  ctx.stroke();
  ctx.closePath();
}

function circle() {
  ctx.fillStyle = 'red';
  ctx.beginPath();
  ctx.arc(X, Y, 20, 0, Math.PI * 2);
  ctx.closePath();
  ctx.fill();
}

function direction() {
  ctx.fillStyle = 'blue';
  ctx.beginPath();
  ctx.arc(positionX + X, positionY + Y, 10, 0, Math.PI * 2);
  ctx.closePath();
  positionX = 35 * Math.sin(angle);
  positionY = 35 * Math.cos(angle);
  ctx.fill();
}

function animate() {
  if (mouseButtonDown) {
    X += positionX / 10;
    Y += positionY / 10;
  } else {
    angle += 0.05;
  }
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  circle();
  direction();
  drawHistory();
  requestAnimationFrame(animate);
}
animate();
<canvas id="canvas1"></canvas>