2012-03-02 10 views
29

Sto usando la funzione clip() su una tela.Come anti-alias bordi della clip() nella tela html5 in Chrome Windows?

Risultati: using canvas clip in various browsers

Come si può vedere la versione Chrome ha jaggies orribili/aliasing lungo i bordi. Come posso risolvere questo?

codice per riprodurre:

http://jsfiddle.net/ZRA76/:

<canvas id="test" width="300" height="300"></canvas>​ 

<script type="text/javascript"> 
    cv = document.getElementById("test"); 
    ctx = cv.getContext("2d"); 

    var im = new Image(); 
    im.onload = function() { 
     ctx.beginPath(); 
     ctx.arc(110, 110, 100, 0, 2*Math.PI, true); 
     ctx.clip(); 
     ctx.drawImage(im, 0, 0); 
    } 
    im.src = "http://placekitten.com/300/300"; 
</script> 
+0

Mi sono imbattuto in questo problema pure. Quello che ho fatto è stato disegnare un cerchio nello stesso punto dell'immagine, dietro di esso, con raggio maggiore di 1 o 2 px. Mantieni il colore simile e vai, "anti alias". – Automatico

risposta

2

dalle risposte sulla Can I turn off antialiasing on an HTML <canvas> element? sembra che si tratta di browser specifico. È anche attivo bug report nel progetto google code chromium. Scusate, ma sembra che per il momento non abbiate fortuna.

+1

Ora la correzione del bug è in stato di sviluppo in [chrome dashboard] (https://www.chromestatus.com/features/4871530282483712). Come scritto in [numeri] (https://code.google.com/p/chromium/issues/detail?id=422984), altri browser (IE, Firefox, Safari) 'clip()' sono antialias. – sapics

-1

Utilizzare la clip svg. Funziona come un fascino ma non è così conveniente da usare.

5

Mi sono imbattuto nello stesso problema con Chrome e clip().

Nella mia circostanza ho raggiunto una migliore compatibilità con il browser impostando canvas globalCompositeOperation.

context.globalCompositeOperation = 'source-atop'; 

Quindi disegna la tua forma, un cerchio in questo caso. Quindi passa a "source-atop" e disegna l'immagine del tuo gattino.

Nota, questa è una soluzione rapida per il disegno di base e presuppone un'area di disegno vuota. Il disegno su tela precedente influirà sulla tua clip.

+0

Questa soluzione funziona molto bene, grazie. Un arco per la clip e un arco per la traccia. Semplice. Credo che la soluzione di canvas scratch sia troppo complicata e lenta per questo problema a meno che tu non abbia qualche problema con NON volere il tratto. – mattdlockyer

+0

Sono stato in grado di applicare questo, oltre alla tecnica "back-canvas", per ridurre un brutto bordo frastagliato quando stavo girando un video su tela: http://codepen.io/paceaux/pen/egLOeR Grazie per condivisione. – paceaux

12

La mia correzione per questo è di disegnare un tratto sottile (2px) bianco allo stesso raggio dopo aver disegnato l'immagine. Copre bene l'aliasing e sembra a posto tra i browser.

+0

Una grande idea! Grazie!! – Keith

+0

Ho lottato con questo oggi per più di un'ora, una soluzione così semplice e straordinaria :) – trueicecold

+0

SÌ, QUESTO, CHIARO, <3! –

22

Se si sta eseguendo un disegno complesso a strati, è possibile utilizzare globalCompositeOperation per emulare il ritaglio in una seconda area di lavoro. È quindi possibile utilizzare drawImage per copiare nuovamente l'area di lavoro nella tela originale. Non posso garantire le prestazioni di questo approccio, ma è l'unico modo che conosco per ottenere quello che vuoi.

//set-up - probably only needs to be done once 
var scratchCanvas = document.createElement('canvas'); 
scratchCanvas.width = 100; 
scratchCanvas.height = 100; 
var scratchCtx = scratchCanvas.getContext('2d'); 


//drawing code 
scratchCtx.clearRect(0, 0, scratchCanvas.width, scratchCanvas.height); 

scratchCtx.globalCompositeOperation = 'source-over'; //default 

//Do whatever drawing you want. In your case, draw your image. 
scratchCtx.drawImage(imageToCrop, ...); 


//As long as we can represent our clipping region as a single path, 
//we can perform our clipping by using a non-default composite operation. 
//You can think of destination-in as "write alpha". It will not touch 
//the color channel of the canvas, but will replace the alpha channel. 
//(Actually, it will multiply the already drawn alpha with the alpha 
//currently being drawn - meaning that things look good where two anti- 
//aliased pixels overlap.) 
// 
//If you can't represent the clipping region as a single path, you can 
//always draw your clip shape into yet another scratch canvas. 

scratchCtx.fillStyle = '#fff'; //color doesn't matter, but we want full opacity 
scratchCtx.globalCompositeOperation = 'destination-in'; 
scratchCtx.beginPath(); 
scratchCtx.arc(50, 50, 50, 0, 2 * Math.PI, true); 
scratchCtx.closePath(); 
scratchCtx.fill(); 


//Now that we have a nice, cropped image, we can draw it in our 
//actual canvas. We can even draw it over top existing pixels, and 
//everything will look great! 

ctx.drawImage(scratchCanvas, ...); 

Il motivo per cui lo facciamo in una tela zero è quella destinazione-in è un'operazione piuttosto distruttivo. Se avevi già disegnato alcune cose nella tela principale (forse hai messo un gradiente gradevole sullo sfondo), e poi volevi disegnare un'immagine ritagliata, il cerchio di ritaglio avrebbe anche ritagliato tutto ciò che avevi già disegnato. Naturalmente, se la tua situazione particolare è più semplice (forse TUTTI quelli che vuoi disegnare è un'immagine ritagliata), puoi rinunciare alla tela antigraffio.

È possibile giocare con le diverse modalità di ritaglio su my demo page. La riga in basso (con i gradienti) non è troppo utile per te, ma la riga in alto (con il cerchio e il quadrato) è molto più rilevante.

modificare

Ops, ho accidentalmente forked your JSFiddle per dimostrare la tecnica.

+0

Signore, ho salvato la giornata! – enyce12

+0

grazie amico! Le sue opere!!! –

Problemi correlati