Ad

Remove Context Arc From Canvas

I am working on a project where user upload structural diagram(engineering diagram). When I user double click on the intended location on canvas the speech to text engine turns on and listen for user comments and then it draw a small circle with different colors and fill text (count) on that location. I am saving comments, counts, coordinates of arc and other things in react state and displaying the list in a component with edit and delete button. When user press the delete button. comment and other property gets deleted from the state.

I want to remove the drawn arc from the canvas. How can I do it?

I have tried clearRect. But it is not working in this case.

Please let me know.


 componentDidMount() {
    const img = this.refs.image;
    const canvas = this.refs.canvas;
    const ctx = canvas.getContext('2d');
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;

    img.onload = () => {
      ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
      ctx.font = "40px Courier";
      ctx.fillText('Drawing 1', 200, 100);
    }
  }
 drawCircle(x, y, getcolor) {

    const canvas = this.refs.canvas;
    const ctx = canvas.getContext("2d");
    ctx.beginPath();
    ctx.arc(x, y, 8, 0, Math.PI * 2, false);
    ctx.strokeStyle = "black";
    ctx.stroke();
    ctx.fillStyle = getcolor;
    ctx.fill();
    ctx.closePath();

    // Text
    ctx.beginPath();
    ctx.font = "20px Arial"
    ctx.fillStyle = "#00538a";
    ctx.textAlign = "center";
    ctx.fillText(this.state.count, x , y - 20);
    ctx.fill();
    ctx.closePath();
  }

 remove(id) {
    this.setState({
      comments: this.state.comments.filter(c => c.id !== id)
    });
    const canvas = this.refs.canvas;
    const ctx = canvas.getContext('2d');
    const arc = this.state.comments.filter(c => c.id === id);
    let x = arc[0].coordinates.x;
    let y = arc[0].coordinates.y
    console.log("TCL: Drawing -> remove -> arc", arc[0].coordinates);
    ctx.beginPath();
    ctx.arc(x, y, 8, 0, Math.PI * 2, false);
    ctx.clip();
    ctx.clearRect(x-8, y-8, 16,16);
  }

Thanks Meet

Ad

Answer

As I mentioned in my comments the way you're trying to remove a circle from the canvas ain't gonna work.

If you call clearRect() on the canvas, it will essentially overwrite the target area including your original background image.

Instead you need to keep track of the circles - more precisely the position at which those should be drawn - using an array.

If you click the canvas -> add a circle element to an array -> clear the canvas -> draw the diagram again -> loop over the array to draw the circles on top

If you click the remove button of a circle -> search the array for this particular circle -> remove it from the array -> clear the canvas -> draw the diagram again -> loop over the array to draw the circles on top

Here's an example to illustrate what I'm talking about:

var comments = new Array();
var canvas = document.createElement("canvas");
canvas.style="float:left;"
canvas.width = 400;
canvas.height = 200;
document.body.appendChild(canvas);
var ctx = canvas.getContext("2d");

function updateCanvas() {
  ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
  ctx.font = "40px Courier";
  ctx.fillText('Drawing 1', 200, 100);
  for (var a = 0; a < comments.length; a++) {
    ctx.beginPath();
    ctx.arc(comments[a].x, comments[a].y, 8, 0, Math.PI * 2, false);
    ctx.strokeStyle = "black";
    ctx.stroke();
    ctx.fillStyle = "black";
    ctx.fill();
    ctx.closePath();
  }
}

var img = new Image();
img.onload = () => {
  updateCanvas();
}
img.src = "https://picsum.photos/id/59/400/200";

function addCircle(e) {

  var div = document.createElement("div");
  div.innerHTML = "remove" + comments.length;
  document.body.appendChild(div);
  div.addEventListener("click", function(e) {
  
    for (var a = 0; a < comments.length; a++) {
      if (comments[a].div == e.target) {
        comments.splice(a, 1);
        break;
      }
    }
    document.body.removeChild(e.target);
    updateCanvas();
  });
  
  comments.push({
    x: e.clientX,
    y: e.clientY,
    div: div
  });
  updateCanvas();
}

canvas.addEventListener("click", addCircle);

Everytime you click on the picture a 'remove' div will be created to the right of the canvas. if you click it, the associated circle will be removed.

Ad
source: stackoverflow.com
Ad