【问题标题】:Remove context Arc from canvas从画布中删除上下文 Arc
【发布时间】:2019-05-14 12:40:00
【问题描述】:

我正在做一个用户上传结构图(工程图)的项目。当我用户双击画布上的预期位置时,语音到文本引擎会打开并收听用户 cmets,然后它会绘制一个具有不同颜色的小圆圈并在该位置填充文本(计数)。我在反应状态下保存 cmets、计数、弧坐标和其他东西,并在带有编辑和删除按钮的组件中显示列表。当用户按下删除按钮时。评论和其他属性被从状态中删除。

我想从画布上移除绘制的弧线。我该怎么做?

我已经尝试过 clearRect。但在这种情况下它不起作用。

请告诉我。


 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);
  }

谢谢 见面

【问题讨论】:

  • 为什么clearRect 在这种情况下不起作用?你能举一个有效的例子吗?
  • 没有看到你的代码,事情有点难,但理论上每次你在画布上添加/删除这样的弧线时,你都需要重新绘制整个画布。因此,如果您想删除某些内容,请清除画布,再次绘制图表并最终绘制剩余的弧线。
  • 我已经添加了一些代码。
  • 图表不是画布的一部分?
  • 图像在画布中。我也添加了 componentDidMount 代码

标签: javascript reactjs html html5-canvas


【解决方案1】:

正如我在我的 cmets 中提到的,你试图从画布上删除一个圆圈的方式是行不通的。

如果您在画布上调用 clearRect(),它实际上会覆盖目标区域,包括您的原始背景图像。

相反,您需要使用数组来跟踪圆 - 更准确地说是应该绘制圆的位置。

如果单击画布 -> 将圆形元素添加到数组 -> 清除画布 -> 再次绘制图表 -> 循环遍历数组以在顶部绘制圆圈

如果您单击圆的删除按钮 -> 在数组中搜索此特定圆 -> 从数组中删除它 -> 清除画布 -> 再次绘制图表 -> 循环遍历数组以在其上绘制圆顶

这里有一个例子来说明我在说什么:

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);

每次单击图片时,画布右侧都会创建一个“删除”div。如果您点击它,相关的圈子将被删除。

【讨论】:

    最近更新 更多