2010-11-23 13 views
42

Cómo activar el anti-aliasing en un canvas.HTML5 Canvas y Anti-aliasing

El siguiente código no dibuja una línea suave:

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

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

De acuerdo con [esta pregunta StackOverflow] (http://stackoverflow.com/questions/195262/can -i-turn-off-antialiasing-on-an-html-canvas-element) parecería que el lienzo * es * anti-aliased por defecto. ¿Qué OS/navegador/versión estás usando? – Phrogz

+2

Cuando dices que no es fácil, ¿qué quieres decir? ¿Estás viendo bordes/píxeles irregulares o solo está borroso? –

+0

Ocurre en Firefox Mobile en Android, hay un borde gris feo alrededor de la línea roja. –

Respuesta

19

Anti-aliasing no puede ser encendido o apagado, y es controlada por el navegador.

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

+5

Eso no es verdad. Se puede activar y desactivar con ctx.imageSmoothingEnabled. – zachdyer

+7

imageSmoothingEnabled se aplica a rellenos de patrón y drawImage, no afecta el suavizado general. http://www.whatwg.org/specs/web-apps/current-work/multipage/the- canvas-element.html#image-smoothing – Gaurav

+1

Oh, en ese caso, tal vez sea la tarjeta de video la que manejaría eso. – zachdyer

16

No he necesitado para activar el suavizado porque está en forma predeterminada, pero he necesitado para apagarlo. Y si se puede apagar, también se puede encender.

ctx.imageSmoothingEnabled = true; 

por lo general lo apago cuando estoy trabajando en mi lienzo rpg por lo que cuando el zoom en las imágenes no se ven borrosas.

+5

imageSmoothingEnabled se aplica a rellenos de patrón y drawImage, no afecta el suavizado general. http://www.whatwg.org/specs/web-apps/current-work/multipage/the- canvas-element.html # image-smoothing – Gaurav

5

Aquí hay una solución alternativa que requiere dibujar líneas píxel por píxel, pero evitará el anti aliasing.

// 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 
    } 
} 

Básicamente, se encuentra la longitud de la línea, y paso a paso transversal esa línea, el redondeo de cada posición, y rellenando un píxel.

de llamadas con

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

No creo que getAngle sea necesario para dibujar líneas. Todo lo que necesitas hacer es dividir la diferencia entre los dos puntos por el 'dist' y multiplicar eso por 'i'. ¿Me equivoco? –

+0

sí, estás en lo correcto. Acabo de usar ángulos para mayor claridad ...? Supongo que – Overcode

+1

holy toledo ¡me has ahorrado un montón de tiempo! Hace aproximadamente un año comencé a trabajar en una aplicación web de pintura basada en píxeles, y me frustraba la incapacidad de desactivar el anti-aliasing. Creo que la única identificación de solución encontrada en ese momento funcionaba tan lentamente que no tenía esperanza, ¡pero la tuya funciona increíblemente rápido y hace exactamente lo que yo necesito! ¡¡¡gracias!!! – steve

35

Puede traducir la lona por la distancia de medio píxel.

ctx.translate(0.5, 0.5); 

Inicialmente el punto de posicionamiento del lienzo entre los píxeles físicos.

+2

Esto lo hizo por mí. – Qix

+0

Tenga en cuenta que si borra su lienzo utilizando el método de establecer el ancho a sí mismo: canvas.width = canvas.width Esto reiniciará la matriz de transzlation y tendrá que traducir por medio píxel de nuevo. Puede evitar esto usando clearRect() en su lugar. – Richard

+0

Esta es la única respuesta que realmente resuelve el problema de OP –

1

Si necesita control de nivel de píxel sobre lienzo, puede hacerlo usando createImageData y putImageData.

HTML:

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

y 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