簡體   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