eliminazione di aree circolari da Canvas HTML5

Sembra che l’unico modo per cancellare una regione da una canvas sia usare il comando clearRect () – Ho bisogno di cancellare una circonferenza (sto mascherando le aree da una canvas piena, punto luci in questo caso specifico) e nonostante tutti i tentativi non sembra ansible

Ho provato a disegnare un cerchio con un valore alfa pari a 0 ma semplicemente non apparirebbe nulla a meno che l’alfa fosse più alto (che è contrario al punto: P) – Presumo perché un contex.fill () lo disegna come add e non come un sostituto .

Qualche suggerimento su come potrei essere in grado di cancellare (rapidamente) i cerchi per scopi di maschera?

Usa .arc per creare un tratto circolare e quindi usa .clip() per renderlo l’area di ritaglio corrente.

Quindi puoi usare .clearRect() per cancellare l’intero canvas, ma cambierà solo l’area ritagliata.

Se stai realizzando un gioco o qualcosa in cui spremere ogni aspetto della performance, dai un’occhiata a come ho fatto questa risposta: Canvas – Riempi un rettangolo in tutte le aree che sono completamente trasparenti

In particolare, la modifica della risposta che porta a questo: http://jsfiddle.net/a2Age/2/

I grandi vantaggi qui:

  • Nessun utilizzo di percorsi (lento)
  • Nessun uso di clip (lento)
  • Nessuna necessità di salvataggio / ripristino (poiché non c’è modo di ripristinare un’area di ritaglio senza cancellare tutto lo stato (1), significa che è necessario utilizzare anche il salvataggio / ripristino)

(1) In realtà mi sono lamentato di questo e resetClip () è stato inserito nella specifica ufficiale a causa di esso, ma ci vorrà un po ‘prima che i browser lo implementino.

Codice

 var ctx = document.getElementById('canvas1').getContext('2d'), ambientLight = 0.1, intensity = 1, radius = 100, amb = 'rgba(0,0,0,' + (1 - ambientLight) + ')'; addLight(ctx, intensity, amb, 200, 200, 0, 200, 200, radius); // First circle addLight(ctx, intensity, amb, 250, 270, 0, 250, 270, radius); // Second circle addLight(ctx, intensity, amb, 50, 370, 0, 50, 370, radius, 50); // Third! ctx.fillStyle = amb; ctx.globalCompositeOperation = 'xor'; ctx.fillRect(0, 0, 500, 500); function addLight(ctx, intsy, amb, xStart, yStart, rStart, xEnd, yEnd, rEnd, xOff, yOff) { xOff = xOff || 0; yOff = yOff || 0; var g = ctx.createRadialGradient(xStart, yStart, rStart, xEnd, yEnd, rEnd); g.addColorStop(1, 'rgba(0,0,0,' + (1 - intsy) + ')'); g.addColorStop(0, amb); ctx.fillStyle = g; ctx.fillRect(xStart - rEnd + xOff, yStart - rEnd + yOff, xEnd + rEnd, yEnd + rEnd); } 
 canvas { border: 1px solid black; background-image: url('http://placekitten.com/500/500'); } 
  

Hai alcune opzioni.

Innanzitutto, ecco una funzione che useremo per riempire un cerchio.

 var fillCircle = function(x, y, radius) { context.beginPath(); context.arc(x, y, radius, 0, 2 * Math.PI, false); context.fill(); }; 

clip()

 var clearCircle = function(x, y, radius) { context.beginPath(); context.arc(x, y, radius, 0, 2 * Math.PI, false); context.clip(); context.clearRect(x - radius - 1, y - radius - 1, radius * 2 + 2, radius * 2 + 2); }; 

Vedi questo su jsFiddle .


globalCompositeOperation

 var clearCircle = function(x, y, radius) { context.save(); context.globalCompositeOperation = 'destination-out'; context.beginPath(); context.arc(x, y, radius, 0, 2 * Math.PI, false); context.fill(); context.restore(); }; 

Vedi questo su jsFiddle .


Entrambi hanno dato il risultato desiderato sullo schermo, tuttavia le prestazioni non erano sufficienti nel mio caso, poiché stavo disegnando e cancellando un sacco di cerchi per ogni fotogramma. Alla fine ho trovato un modo diverso per ottenere un effetto simile a quello che volevo semplicemente disegnando linee più spesse su un arco, ma quanto sopra potrebbe ancora essere utile a qualcuno che ha requisiti di performance diversi.

Dati i requisiti, queste risposte vanno bene. Ma diciamo che sei come me e hai dei requisiti aggiuntivi:

  1. Vuoi “cancellare” una parte di una forma che potrebbe essere parzialmente fuori dai limiti della forma che stai cancellando.
  2. Vuoi vedere lo sfondo sotto la forma invece di cancellare lo sfondo.

Per il primo requisito, la soluzione è usare context.globalCompositeOperation = 'destination-out' Il blu è la prima forma e il rosso è la seconda forma. Come puoi vedere, destination-out rimuove la sezione dalla prima forma.

inserisci la descrizione dell'immagine qui

Ecco alcuni esempi di codice:

  explosionCanvasCtx.fillStyle = "red" drawCircle(explosionCanvasCtx, projectile.radius, projectile.radius, projectile.radius) explosionCanvasCtx.fill() explosionCanvasCtx.globalCompositeOperation = 'destination-out' #see https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html drawCircle(explosionCanvasCtx, projectile.radius + 20, projectile.radius, projectile.radius) explosionCanvasCtx.fill() 

Ecco il potenziale problema con questo: il secondo fill() cancellerà tutto ciò che si trova al di sotto, incluso lo sfondo. A volte vorrete solo cancellare la prima forma ma vorrete comunque vedere i livelli sottostanti.

La soluzione è disegnare questo su una canvas temporanea e quindi drawImage per disegnare la canvas temporanea sulla canvas principale. Il codice sarà simile a questo:

  diameter = projectile.radius * 2 console.log "" explosionCanvas = $("") explosionCanvasCtx = explosionCanvas[0].getContext("2d") explosionCanvasCtx.fillStyle = "red" drawCircle(explosionCanvasCtx, projectile.radius, projectile.radius, projectile.radius) explosionCanvasCtx.fill() explosionCanvasCtx.globalCompositeOperation = 'destination-out' #see https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html durationPercent = (projectile.startDuration - projectile.duration) / projectile.startDuration drawCircle(explosionCanvasCtx, projectile.radius + 20, projectile.radius, projectile.radius) explosionCanvasCtx.fill() explosionCanvasCtx.globalCompositeOperation = 'source-over' #see https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html ctx.drawImage(explosionCanvas[0], projectile.pos.x - projectile.radius, projectile.pos.y - projectile.radius) #center 

Usa canvas.getContext("2d").arc(...) per disegnare un cerchio sull’area con il colore di sfondo?

 var canvas = document.getElementById("myCanvas"); var context = canvas.getContext("2d"); context.arc(x, y, r, 0, 2*Math.PI, false); context.fillStyle = "#FFFFFF"; context.fill(); 

Dove x = posizione a sinistra, y = posizione a destra, r = raggio e ctx = area di disegno:

 function clearCircle( x , y , r ){ for( var i = 0 ; i < Math.round( Math.PI * r ) ; i++ ){ var angle = ( i / Math.round( Math.PI * r )) * 360; ctx.clearRect( x , y , Math.sin( angle * ( Math.PI / 180 )) * r , Math.cos( angle * ( Math.PI / 180 )) * r ); } }