繁体   English   中英

在JS中仅擦除画布的拼接元素

[英]Erasing only paticular element of canvas in JS

我想创建类似刮刮卡的东西。 我创建了一个画布并向其中添加了文本,然后在文本上方添加了一个框以将其隐藏。最后写下代码以擦除(擦除)该框。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.font = "30px Arial";
ctx.fillText("Hello World",10,50); 
ctx.globalCompositeOperation = 'source-over';
ctx.fillStyle='red';
ctx.fillRect(0,0,500,500);
function myFunction(event) {
  var x = event.touches[0].clientX;
  var y = event.touches[0].clientY;
  document.getElementById("demo").innerHTML = x + ", " + y;
  ctx.globalCompositeOperation = 'destination-out';
  ctx.arc(x,y,30,0,2*Math.PI);
  ctx.fill();
}

但是问题是它也删除了文本。
我如何只删除该框而不删除文本?

我如何只删除该框而不删除文本?

您不能,您将不得不重新绘制文本。 一旦在文本上方绘制了框,就将其抹掉了,它不再存在。 画布是基于像素的,而不是像SVG一样基于形状的。

画布上下文仅保留一种绘制状态,即一种绘制状态。 如果您修改像素,它将不记得它以前的样子,并且由于它没有内置的图层概念,因此当您清除像素时,它只是一个透明像素。

因此,要实现您想要的目标,最简单的方法就是自己构建这种分层逻辑,例如,通过创建两个“ 屏幕外 ”画布(如“未附加在DOM中”),一个用于可刮擦区域,一个用于背景绘制,应该被揭露。

然后在第三个画布上,每次都绘制两个画布。 这是将向您的用户展示的第三张画布:

 var canvas = document.getElementById("myCanvas"); // the context that will be presented to the user var main = canvas.getContext("2d"); // an offscreen one that will hold the background var background = canvas.cloneNode().getContext("2d"); // and the one we will scratch var scratch = canvas.cloneNode().getContext("2d"); generateBackground(); generateScratch(); drawAll(); // the events handlers var down = false; canvas.onmousemove = handlemousemove; canvas.onmousedown = handlemousedown; canvas.onmouseup = handlemouseup; function drawAll() { main.clearRect(0,0,canvas.width,canvas.height); main.drawImage(background.canvas, 0,0); main.drawImage(scratch.canvas, 0,0); } function generateBackground(){ background.font = "30px Arial"; background.fillText("Hello World",10,50); } function generateScratch() { scratch.fillStyle='red'; scratch.fillRect(0,0,500,500); scratch.globalCompositeOperation = 'destination-out'; } function handlemousedown(evt) { down = true; handlemousemove(evt); } function handlemouseup(evt) { down = false; } function handlemousemove(evt) { if(!down) return; var x = evt.clientX - canvas.offsetLeft; var y = evt.clientY - canvas.offsetTop; scratch.beginPath(); scratch.arc(x, y, 30, 0, 2*Math.PI); scratch.fill(); drawAll(); } 
 <canvas id="myCanvas"></canvas> 

现在,所有这些都可以在同一画布上完成,但是从性能角度来看,这可能不是最好的,因为这意味着生成一个过于复杂的子路径,该子路径应在每次绘制时重新渲染,而且也并不容易实现:

 var canvas = document.getElementById("myCanvas"); var ctx = canvas.getContext('2d'); ctx.font = '30px Arial'; drawAll(); // the events handlers var down = false; canvas.onmousemove = handlemousemove; canvas.onmousedown = handlemousedown; canvas.onmouseup = handlemouseup; function drawAll() { ctx.globalCompositeOperation = 'source-over'; // first draw the scratch pad, intact ctx.fillStyle = 'red'; ctx.fillRect(0,0,500,500); // then erase with the currently being defined path // see 'handlemousemove's note ctx.globalCompositeOperation = 'destination-out'; ctx.fill(); // finally draw the text behind ctx.globalCompositeOperation = 'destination-over'; ctx.fillStyle = 'black'; ctx.fillText("Hello World",10,50); } function handlemousedown(evt) { down = true; handlemousemove(evt); } function handlemouseup(evt) { down = false; } function handlemousemove(evt) { if(!down) return; var x = evt.clientX - canvas.offsetLeft; var y = evt.clientY - canvas.offsetTop; // note how here we don't create a new Path, // meaning that all the arcs are being added to the single one being rendered ctx.moveTo(x, y); ctx.arc(x, y, 30, 0, 2*Math.PI); drawAll(); } 
 <canvas id="myCanvas"></canvas> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM