2008-10-12 13 views
66

Estoy jugando con el elemento <canvas>, líneas de dibujo y tal.¿Puedo desactivar el antialiasing en un elemento HTML <canvas>?

He notado que mis líneas diagonales tienen antialias. Prefiero el aspecto irregular de lo que estoy haciendo, ¿hay alguna forma de desactivar esta característica?

+0

Creo que está más bien relacionado con el navegador. Tal vez sea útil alguna información adicional sobre qué software usará. – Tomalak

+0

Preferiría un método de navegador cruzado, pero un método que funciona en cualquier navegador solo sería interesante para mí – Blorgbeard

+0

. Solo quería ver si había habido algún cambio sobre este tema. – vternal3

Respuesta

39

Para las imágenes ahora hay context.imageSmoothingEnabled= false.

Sin embargo, no hay nada que explícitamente controle el dibujo de líneas. Puede necesitar dibujar sus propias líneas (the hard way) usando getImageData y putImageData.

+0

Me pregunto sobre el rendimiento de un algoritmo de línea de JavaScript ... Podría darle una oportunidad a Bresenham en algún momento. – Blorgbeard

+0

Los vendedores de navegadores están promocionando nuevos motores súper rápidos JS últimamente, por lo que finalmente habría un buen uso para ello. – Kornel

51

Dibuja tus líneas 1-pixel en coordenadas como ctx.lineTo(10.5, 10.5). Dibujar una línea de un píxel sobre el punto (10, 10) significa que este píxel de 1 en esa posición va desde 9.5 hasta 10.5, lo que da como resultado dos líneas que se dibujan en el lienzo.

Un buen truco para no siempre es necesario agregar 0.5 a la coordenada real que desea dibujar si tiene muchas líneas de un píxel, es a ctx.translate(0.5, 0.5) todo su lienzo al principio.

+0

hmm, estoy teniendo problemas para eliminar el anti-aliasing usando esta técnica. Tal vez, estoy extrañando algo? ¿Te importaría publicar un ejemplo en algún lugar? – Xavi

+5

Esto no elimina el antialiasing, pero hace que las líneas antialias se vean mucho mejor, como deshacerse de esas líneas vergonzosas horizontales o verticales que tienen dos píxeles de grosor cuando realmente desea un píxel. –

+0

@porneL: No, las líneas se dibujan entre las esquinas de los píxeles. Cuando tu línea tiene 1 píxel de ancho, se extiende medio píxel en cualquier dirección – Eric

24

Se puede hacer en Mozilla Firefox. Agregue esto a su código:

contextXYZ.mozImageSmoothingEnabled = false; 

En Opera es actualmente una de estas solicitudes, pero es de esperar que se añadirán en breve.

+0

genial. +1 por tu contribución. Me pregunto si la desactivación de AA acelera alineando – marcusklaas

+6

El OP quiere líneas sin anti-alias, pero esto solo funciona en imágenes. Según [la especificación] (http://www.w3.org/TR/2dcontext2/#image-smoothing), determina '" si el patrón se llena y el método drawImage() intentará suavizar las imágenes si sus píxeles no lo hacen alinearse exactamente con la pantalla, al escalar las imágenes "' – rvighne

5

Dibujaría todo usando un algoritmo de línea personalizado como el algoritmo de línea de Bresenham. Mira esta implementación de javascript: http://members.chello.at/easyfilter/canvas.html

Creo que esto definitivamente resolverá tus problemas.

+1

Exactamente lo que necesitaba, lo único que agregaría es que debe implementar 'setPixel (x, y)'; Utilicé la respuesta aceptada aquí: http://stackoverflow.com/questions/4899799/whats-the-best-way-to-set-a-single-pixel-in-an-html5-canvas –

5
ctx.translate(0.5, 0.5); 
ctx.lineWidth = .5; 

Con este combo puedo dibujar lindas líneas de 1px.

+4

No es necesario para establecer lineWidth a .5 ... que lo hará (o debería) solo hacer que sea la mitad de la opacidad. – aaaidan

5

Quiero agregar que tuve problemas al reducir una imagen y dibujar en el lienzo, todavía estaba usando suavizado, aunque no estaba usando al escalar.

que resuelven usando esto:

function setpixelated(context){ 
    context['imageSmoothingEnabled'] = false;  /* standard */ 
    context['mozImageSmoothingEnabled'] = false; /* Firefox */ 
    context['oImageSmoothingEnabled'] = false;  /* Opera */ 
    context['webkitImageSmoothingEnabled'] = false; /* Safari */ 
    context['msImageSmoothingEnabled'] = false;  /* IE */ 
} 

Puede utilizar esta función como esta:

var canvas = document.getElementById('mycanvas') 
setpixelated(canvas.getContext('2d')) 

Tal vez esto es útil para alguien.

9

Se debe gráficos vectoriales antialias

suavizado de líneas es requerido para el correcto trazado de gráficos vectoriales que implica coordenadas no enteras (0.4, 0.4), que todos, pero muy pocos clientes quieren hacer.

Cuando coordenadas dadas no entero, el lienzo tiene dos opciones:

  • Antialias - pintar los píxeles alrededor de la coordenada con respecto a qué tan lejos coordinar el número entero es de no entero uno (el redondeo error).
  • Ronda - aplicar alguna función de redondeo a la coordenada no entera (por lo que 1.4 se convertirá en 1, por ejemplo).

La estrategia posterior funcionará para gráficos estáticos, aunque para gráficos pequeños (un círculo con radio de 2) las curvas mostrarán pasos claros en lugar de curvas suaves.

El problema real es cuando se traducen (mueven) los gráficos - los saltos entre un píxel y otro (1.6 => 2, 1.4 => 1) significan que el origen de la forma puede saltar con relación al padre contenedor (cambiando constantemente 1 píxel hacia arriba/abajo e izquierda/derecha).

Algunos consejos

Consejo # 1: Puede ablandar (o endurecer) antialiasing escalando la lona (digamos por x) a continuación, aplicar la escala recíproco (1/x) a las geometrías usted mismo (no usar el lienzo).

Compare (sin escala):

A few rectangles

con (escala de lona: 0,75; escala Manual: 1,33):

Same rectangles with softer edges

y (escala de lona: 1,33; escala manual de : 0.75):

Same rectangles with darker edges

Consejo n.º 2: Si lo que buscas es un aspecto irregular, intenta dibujar cada forma varias veces (sin borrar). Con cada extracción, los píxeles antialiasing se oscurecen.

Comparar. Después de dibujar una vez:

A few paths

Después de dibujar tres veces:

Same paths but darker and no visible antialiasing.

+0

No proporcionar los comandos exactos es solo una teoría. – vanowm

+0

@vanowm siéntase libre de clonar y jugar con: https://github.com/Izhaki/gefri. Todas las imágenes son capturas de pantalla de la carpeta/demo (con un código ligeramente modificado para la sugerencia n. ° 2). Estoy seguro de que le resultará fácil introducir el redondeo de números enteros en las figuras dibujadas (me tomó 4 minutos) y luego simplemente arrastre para ver el efecto. – Izhaki

1

Aviso un truco muy limitado. Si desea crear una imagen de 2 colores, puede dibujar cualquier forma que desee con el color # 010101 en un fondo con color # 000000. Una vez hecho esto, puede probar cada píxel de la imageData.data [] y ajuste a cualquier valor 0xFF 0x00 no es:

imageData = context2d.getImageData (0, 0, g.width, g.height); 
for (i = 0; i != imageData.data.length; i ++) { 
    if (imageData.data[i] != 0x00) 
     imageData.data[i] = 0xFF; 
} 
context2d.putImageData (imageData, 0, 0); 

El resultado será un negro & imagen no antialiased blanco. Esto no será perfecto, ya que se realizará un antialiasing, pero este antialiasing será muy limitado, el color de la forma será muy similar al del fondo.

Cuestiones relacionadas