2010-11-23 13 views
42

So aktivieren Sie die Anti-Aliasing auf einem Leinwand.HTML5 Canvas und Anti-Aliasing

Der folgende Code keine glatte Linie zeichnen:

var context = mainCanv.getContext("2d"); 
if (context) { 
    context.moveTo(0,0); 
    context.lineTo(100,75); 

    context.strokeStyle = "#df4b26"; 
    context.lineWidth = 3; 
    context.stroke(); 
} 
+3

Nach [diese Frage Stackoverflow] (http://stackoverflow.com/questions/195262/can -i-turn-off-antialiasing-on-einem-html-canvas-element) es scheint, dass die Leinwand * standardmäßig * anti-aliased ist. Welche OS/Browser/Version verwenden Sie? – Phrogz

+2

Wenn Sie sagen, es ist nicht glatt, was meinst du? Sehen Sie gezackte Ränder/Pixel oder ist es nur verschwommen? –

+0

Es passiert bei Firefox Mobile auf Android, es gibt einen hässlichen grauen Rand um die rote Linie. –

Antwort

19

Anti-Aliasing kann nicht ein- oder ausgeschaltet werden, und wird durch den Browser gesteuert.

Can I turn off antialiasing on an HTML <canvas> element?

+5

Das stimmt nicht. Es kann mit ctx.imageSmoothingEnabled ein- und ausgeschaltet werden. – zachdyer

+7

imageSmoothingEnabled wirkt sich auf Musterfüllungen und drawImage aus und hat keinen Einfluss auf das allgemeine Anti-Aliasing. http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#image-smoothing – Gaurav

+1

Oh in diesem Fall ist es vielleicht die Grafikkarte, die damit umgehen würde. – zachdyer

16

Ich habe nicht auf Anti-Aliasing drehen benötigt, da es standardmäßig aktiviert ist, aber ich habe benötigt, um sie auszuschalten. Und wenn es ausgeschaltet werden kann, kann es auch eingeschaltet werden.

ctx.imageSmoothingEnabled = true; 

Ich schließe es in der Regel aus, wenn ich arbeite an meiner Leinwand so rpg, wenn ich in den Bildern heran nicht verschwommen aussehen.

+5

imageSmoothingEnabled bezieht sich auf Musterfüllungen und drawImage, wirkt sich jedoch nicht auf das allgemeine Anti-Aliasing aus. http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html # image-smoothing – Gaurav

5

Hier ist ein Workaround, bei dem Sie Linien Pixel für Pixel zeichnen müssen, aber Anti-Aliasing verhindern.

// some helper functions 
// finds the distance between points 
function DBP(x1,y1,x2,y2) { 
    return Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); 
} 
// finds the angle of (x,y) on a plane from the origin 
function getAngle(x,y) { return Math.atan(y/(x==0?0.01:x))+(x<0?Math.PI:0); } 
// the function 
function drawLineNoAliasing(ctx, sx, sy, tx, ty) { 
    var dist = DBP(sx,sy,tx,ty); // length of line 
    var ang = getAngle(tx-sx,ty-sy); // angle of line 
    for(var i=0;i<dist;i++) { 
     // for each point along the line 
     ctx.fillRect(Math.round(sx + Math.cos(ang)*i), // round for perfect pixels 
        Math.round(sy + Math.sin(ang)*i), // thus no aliasing 
        1,1); // fill in one pixel, 1x1 
    } 
} 

Grundsätzlich man die Länge der Zeile zu finden, und Schritt für Schritt Verfahrweg dieser Linie, um jede Position Abrunden, und in einem Pixel zu füllen.

Nennen Sie es mit

var context = cv.getContext("2d"); 
drawLineNoAliasing(context, 20,30,20,50); // line from (20,30) to (20,50) 
+1

Ich glaube nicht, dass getAngle zum Zeichnen von Linien notwendig ist. Sie müssen lediglich den Unterschied zwischen den beiden Punkten mit "dist" teilen und mit "i" multiplizieren. Liege ich falsch? –

+0

ja du bist richtig. Ich habe nur Winkel für Klarheit verwendet ..? Ich glaube, – Overcode

+1

heiligen Toledo Sie haben mir gerade eine Menge Zeit gerettet! Vor etwa einem Jahr begann ich mit der Arbeit an einer pixelbasierten Mal-Web-App und wurde frustriert, dass ich das Anti-Aliasing nicht deaktivieren konnte. Ich denke, die einzige Lösungs-ID, die zu der Zeit gefunden wurde, lief so langsam, dass es hoffnungslos war, aber deine läuft erstaunlich schnell und macht genau das, wozu ich sie brauche! Danke!!! – steve

35

Sie Leinwand von Halbpixelabstand übersetzen kann.

ctx.translate(0.5, 0.5); 

Anfänglich der Leinwandpositionierungspunkt zwischen den physischen Pixeln.

+2

Das hat es für mich getan. – Qix

+0

Beachten Sie, dass beim Löschen der Zeichenfläche mit der Methode zum Festlegen der Breite auf sich selbst: canvas.width = canvas.width die Transziermatrix zurückgesetzt wird und Sie erneut um ein halbes Pixel verschieben müssen. Sie können dies vermeiden, indem Sie stattdessen clearRect() verwenden. – Richard

+0

Dies ist die einzige Antwort, die tatsächlich löst OPs Problem –

1

Wenn Sie Pixel-Level-Kontrolle über Canvas benötigen, können Sie createImageData und putImageData verwenden.

HTML:

<canvas id="qrCode" width="200", height="200"> 
    QR Code 
</canvas> 

und JavaScript:

function setPixel(imageData, pixelData) { 
    var index = (pixelData.x + pixelData.y * imageData.width) * 4; 
    imageData.data[index+0] = pixelData.r; 
    imageData.data[index+1] = pixelData.g; 
    imageData.data[index+2] = pixelData.b; 
    imageData.data[index+3] = pixelData.a; 
} 

element = document.getElementById("qrCode"); 
c = element.getContext("2d"); 

pixcelSize = 4; 
width = element.width; 
height = element.height; 


imageData = c.createImageData(width, height); 

for (i = 0; i < 1000; i++) { 
    x = Math.random() * width/pixcelSize | 0; // |0 to Int32 
    y = Math.random() * height/pixcelSize| 0; 

    for(j=0;j < pixcelSize; j++){ 
    for(k=0;k < pixcelSize; k++){ 
    setPixel(imageData, { 
     x: x * pixcelSize + j, 
     y: y * pixcelSize + k, 
     r: 0 | 0, 
     g: 0 | 0, 
     b: 0 * 256 | 0, 
     a: 255 // 255 opaque 
     }); 
     } 
    } 
} 

c.putImageData(imageData, 0, 0); 

Working sample here