如何在可视化橡皮筋的同时在画布上绘制多个形状?

时间:2019-12-11 16:36:22

标签: javascript html html5-canvas

我正在使用画布和js制作带有橡皮筋的绘画工具。当前,它绘制椭圆形,但是每次我开始拖动以绘制新形状时-由于rubberBand功能的特定性,先前的形状会擦除,导致每次清除画布。有什么办法可以解决这个问题?

这是jsfiddle链接:https://jsfiddle.net/ThePanda/bspf5v40/

HTML(index.html):

<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="./style.css" />
    <script src="index.js"></script>
  </head>
  <body>
    <div style="position:absolute; top:4px; left:4px;"><canvas id="canvas"></canvas></div>
    <script>
      canvasEngine();
    </script>
  </body>
</html>

CSS(style.css):

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

#canvas {
    border: 2px solid black;
}

JavaScript(index.js):

function canvasEngine() {
  let canvas = document.getElementById('canvas');
  let ctx = canvas.getContext('2d');

  canvas.height = window.innerHeight - 12;
  canvas.width = window.innerWidth - 12;

  //letiables
  let canvasStartX = 4;
  let canvasStartY = 4;
  let lastMouseY, lastMouseX;
  let mouseX, mouseY;
  let width, height;

  let mousedown = false;

  //Mousedown
  function startPosition(e) {
    lastMouseX = parseInt(e.clientX - canvasStartX);
    lastMouseY = parseInt(e.clientY - canvasStartY);
    mousedown = true;
  };

  //Mousemove
  function rubberBand(e) {
    if (!mousedown) return;

    mouseX = parseInt(e.clientX - canvasStartX);
    mouseY = parseInt(e.clientY - canvasStartY);

    ctx.clearRect(0,0,canvas.width,canvas.height);

    ctx.beginPath();
    width = mouseX-lastMouseX;
    height = mouseY-lastMouseY;
    ctx.rect(lastMouseX,lastMouseY,width,height);
    ctx.strokeStyle = 'blue';
    ctx.lineWidth = 2;
    ctx.stroke();
  };

  //Mouseup
  function finishedPosition(e) {
    mousedown = false;

    mouseX = parseInt(e.clientX - canvasStartX);
    mouseY = parseInt(e.clientY - canvasStartY);

    width = mouseX - lastMouseX;
    height = mouseY - lastMouseY;

    const rw = Math.abs(width/2);
    const rh = Math.abs(height/2);

    let centerX = mouseX - width/2;
    let centerY = mouseY - height/2;

    ctx.clearRect(0,0,canvas.width,canvas.height);

    ctx.beginPath();
    ctx.ellipse(centerX,centerY,rw,rh,0,0,2 * Math.PI);
    ctx.strokeStyle = color;
    ctx.lineWidth = 5;
    ctx.stroke();
  };

  canvas.addEventListener("mousedown", startPosition);
  canvas.addEventListener("mousemove", rubberBand);
  canvas.addEventListener("mouseup", finishedPosition);
};

1 个答案:

答案 0 :(得分:1)

您的代码对于您要实现的目标基本上是正确的。

主要问题是,每次绘制新内容时,您都会呼叫ctx.clearRect。这样,整个画布就被清除了,旧的椭圆也消失了。

我已尝试对您的代码进行最小的更改以解决此问题:

function canvasEngine() {
  let canvas = document.getElementById('canvas');
  let ctx = canvas.getContext('2d');
    
  canvas.height = window.innerHeight - 12;
  canvas.width = window.innerWidth - 12;
  
  //letiables
  let canvasStartX = 4;
  let canvasStartY = 4;
  let lastMouseY, lastMouseX;
  let mouseX, mouseY;
  let width, height;
  
  let mousedown = false;
  
  let ellipses = [];

	function drawEllipse(ellipse) {
  	ctx.beginPath();
  	ctx.ellipse(
    	ellipse.centerX,
      ellipse.centerY,
      ellipse.rw,
      ellipse.rh,
      0,
      0,
      2 * Math.PI
    );
    ctx.stroke();
  }

	function drawEllipses() {
  	ctx.strokeStyle = 'black';
    ctx.lineWidth = 5;
  	
  	ellipses.forEach(drawEllipse)
  }

  //Mousedown
  function startPosition(e) {
    lastMouseX = parseInt(e.clientX - canvasStartX);
    lastMouseY = parseInt(e.clientY - canvasStartY);
    mousedown = true;
  };
  
  //Mousemove
  function rubberBand(e) {
    if (!mousedown) return;

    mouseX = parseInt(e.clientX - canvasStartX);
    mouseY = parseInt(e.clientY - canvasStartY);
    
    ctx.clearRect(0,0,canvas.width,canvas.height);
    
    drawEllipses();

    ctx.beginPath();
    width = mouseX-lastMouseX;
    height = mouseY-lastMouseY;
    ctx.rect(lastMouseX,lastMouseY,width,height);
    ctx.strokeStyle = 'blue';
    ctx.lineWidth = 2;
    ctx.stroke();
  };

  //Mouseup
  function finishedPosition(e) {
    mousedown = false;

    mouseX = parseInt(e.clientX - canvasStartX);
    mouseY = parseInt(e.clientY - canvasStartY);

    width = mouseX - lastMouseX;
    height = mouseY - lastMouseY;
    
    const rw = Math.abs(width/2);
    const rh = Math.abs(height/2);
    
    let centerX = mouseX - width/2;
    let centerY = mouseY - height/2;
    
    // Add the ellipse to the list of ellipses
    ellipses.push({ centerX, centerY, rw, rh })

    ctx.clearRect(0,0,canvas.width,canvas.height);
    drawEllipses();
  };
  
  canvas.addEventListener("mousedown", startPosition);
  canvas.addEventListener("mousemove", rubberBand);
  canvas.addEventListener("mouseup", finishedPosition);
};

canvasEngine();
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

#canvas {
    border: 2px solid black;
}
<div style="position:absolute; top:4px; left:4px;"><canvas id="canvas"></canvas></div>