2016-11-09 2 views
0

Ich habe ein Programm erstellt, um Planeten Sprites zu generieren. Ich mache das, indem ich einen kreisförmigen Pfad erzeuge, der ctx.clip() ausführt, um alle folgenden Ebenen innerhalb des Kreises zu behalten, dann eine schwarze und transparente Textur-Ebene zu zeichnen, dann ein zufällig gefärbtes Rechteck über die gesamte Leinwand, dann einen Schatten und Glühen darüber Von allem. Das Problem ist, dass eine farbige Linie auch nach dem Clipping unter dem Kreis erscheint, und ich bin mir nicht sicher warum. Ich brauche das entfernt.HTML5 Canvas ctx.clip() Methode auf einem Kreis verwendet, lässt eine Linie unter dem Kreis

Hier ist eine Geige. Die letzte Zeile setzt den Code auf jede halbe Sekunde: https://jsfiddle.net/tzkwmzqu/4/

+0

Würde es helfen, wenn ich mit einem Bild des Fehlers aktualisiert? – Howzieky

+0

Oh mein Gott, ich vermisste die Geige! Deine Geige scheint jetzt zu arbeiten, danke! Wenn es plötzlich wie meine alten bricht, werde ich zurück kommentieren – Howzieky

Antwort

2

Ich bin mir nicht sicher, ob ich Ihr Problem verstehe, aber ich nehme an, dass Sie über das anti-aliasing Problem sprechen.

Momentan zeichnen Sie viel über Ihren ausgeschnittenen Bereich.
Bei jedem Zeichnen kommen neue Anti-Aliasing-Artefakte zum Glätten der neuesten Zeichnung. Am Ende sind die halbtransparenten Pixel nun vollständig undurchsichtig.
Auf der anderen Seite, mit globalCompositeOperation wie 'destination-in', benötigen Sie nur eine Zeichnung, um das Compositing (~ Clipping) zu machen. Sie akkumulieren also keine Artefakte. Aber selbst wenn, gCO ist global und da es die Transparenz berücksichtigt, wäre die Akkumulation weniger wichtig.

var ctx1 = clip.getContext('2d'); 
 
var ctx2 = gCO.getContext('2d'); 
 
var ctx3 = gCO2.getContext('2d'); 
 

 
ctx1.beginPath(); 
 
ctx1.arc(150, 150, 150, 0, Math.PI*2) 
 
ctx1.clip(); 
 
// drawing multiple times on this clipped area will increase artifacts 
 
ctx1.fillRect(0,0,300, 150); 
 
ctx1.fillRect(0,0,300, 150); 
 
ctx1.fillRect(0,0,300, 150); 
 
ctx1.fillRect(0,0,300, 150); 
 

 
ctx2.beginPath(); 
 
ctx2.arc(150, 150, 150, 0, Math.PI*2) 
 
ctx2.fillRect(0,0,300, 150); 
 
ctx2.globalCompositeOperation = 'destination-in'; 
 
//With gCO you only draw once, but even if you did draw multiple times, there would still be less artifacts 
 
ctx2.fill(); 
 
ctx2.fill(); 
 
ctx2.fill(); 
 
ctx2.fill(); 
 
ctx2.globalCompositeOperation = 'source-over'; 
 

 
ctx3.beginPath(); 
 
ctx3.arc(150, 150, 150, 0, Math.PI*2) 
 
ctx3.fillRect(0,0,300, 150); 
 
ctx3.globalCompositeOperation = 'destination-in'; 
 
// only one drawing needed: 
 
ctx3.fill(); 
 
ctx3.globalCompositeOperation = 'source-over'; 
 

 
ctx1.fillStyle = ctx2.fillStyle = ctx3.fillStyle = "white"; 
 
ctx1.fillText('clipping', 120, 100); 
 
ctx2.fillText('compositing', 120, 100); 
 
ctx3.fillText('single compositing', 120, 100);
canvas{ 
 
    border: 1px solid; 
 
    }
<canvas id="clip"></canvas><canvas id="gCO"></canvas><canvas id="gCO2"></canvas>

Einige unabhängigen Notizen über Ihren Code:

closePath nicht das Ende der Pfadangabe markieren, nur ein neuer beginPath() Anruf tut. ctx.fillStyle = 'transparent'; ctx.fill() wird nichts tun. Nur putImageData, clearRect Methoden und globalCompositeOperation + Zeichenmethode kann transparente Pixel erzeugen.

So, hier ist alles oben in einem Snippet:

/* Load images */ 
 
var texture = new Image(); 
 
texture.src = "http://i.imgur.com/0qMwa8p.png"; 
 
var shadow = new Image(); 
 
shadow.src = "http://i.imgur.com/pX3HVFY.png"; 
 

 
/* Create the canvas and context references */ 
 
var canvas = document.getElementById("game"); 
 
canvas.style.width = (canvas.width = 512) + "px"; 
 
canvas.style.height = (canvas.height = 512) + "px"; 
 
var ctx = canvas.getContext("2d"); 
 

 
/* render */ 
 
function render() { 
 
    /* Size of planets */ 
 
    var scale = Math.random() + 1 
 

 
    
 
    // We don't need to save/restore the canvas state now, 
 
    // simply remember to set the gCO back to 'source-over' 
 
    // here it done at the end of the function 
 
    
 
    /* Clear canvas for redraw */ 
 
    ctx.clearRect(0, 0, canvas.width, canvas.height); 
 
    /* Place texture onto planet */ 
 
    ctx.globalAlpha = Math.random() * .5 + .5; 
 
    ctx.drawImage(texture, (Math.round(Math.random() * 256) - 128 * scale), (Math.round(Math.random() * 256) - 128 * scale), texture.naturalWidth * scale, texture.naturalHeight * scale) 
 

 
    /* Color Planet */ 
 
    ctx.globalAlpha = 1; 
 
    ctx.globalCompositeOperation = "multiply"; 
 
    var color = "hsl(" + Math.random() * 256 + ", 100%, 50%)" 
 
    ctx.fillStyle = color; 
 
    ctx.fillRect(0, 0, canvas.width, canvas.height) 
 

 
    /* Give planet its shine and shadow */ 
 
    ctx.globalCompositeOperation = "source-over"; 
 
    ctx.drawImage(shadow, Math.round(Math.random() * 200 - 128 * scale), Math.round(Math.random() * 200 - 128 * scale), shadow.naturalWidth * scale, shadow.naturalHeight * scale) 
 

 
    // instead of clipping, use gCO 
 
    ctx.globalCompositeOperation = 'destination-in'; 
 
    ctx.beginPath(); 
 
    ctx.arc(256, 256, 128 * scale, 0, 2 * Math.PI); 
 
    ctx.fill(); 
 
    // reset gCO 
 
    ctx.globalCompositeOperation = 'source-over'; 
 
} 
 
render() 
 
window.interval = setInterval(render, 500)
#game { 
 
    border: 1px solid black; 
 
    background-color: black; 
 
}
<canvas id="game"></canvas>

Verwandte Themen