2010-09-07 11 views
5

Estoy leyendo un libro en Html5 y sobre lienzo, el siguiente código generará líneas de 1 píxel de espesor ... Utiliza 0.5 como la coordenada. Si se cambia a 0 o 10, o a un entero, las líneas serán grises y de 2 píxeles de grosor. ¿Porqué es eso? Que lo más extraño que he visto últimamente ... toda la programación anterior en Apple o Win32 API, van por coordenadas enteras.En Html5, dibuje de (0.5, 0) a (0.5, 600) para obtener una línea gruesa de 1 píxel en el lienzo. El 0.5 es extraño?

<!DOCTYPE html> 

<body> 
<canvas id="c" width="800" height="600"></canvas> 
</body> 

<script> 

var c_canvas = document.getElementById("c") 
var context = c_canvas.getContext("2d") 

for (x = 0.5; x < 500; x += 10) { 
    context.moveTo(x, 0) 
    context.lineTo(x, 375) 
} 
context.strokeStyle = "#000" 
context.stroke() 


</script> 

Otra cosa extraña es, para conseguir un 1 píxel por 1 píxel punto negro, tengo que recurrir a 0,5 para x, pero el uso de números enteros para y

for (x = 0.5; x < 500; x += 10) { 
    context.moveTo(x, 0) 
    context.lineTo(x, 1) 
} 

si utilizo el siguiente, entonces consigo un gris, "punto largo"

for (x = 0.5; x < 500; x += 10) { 
    context.moveTo(x, 0.5) 
    context.lineTo(x, 1.5) 
} 

Respuesta

6

no estoy seguro de que es lo mismo con HTML 5, pero se ve muy similar a cómo la biblioteca Qt se ocupa de la pintura. Esencialmente, las coordenadas (0,0) y (1,1) definen un píxel en la esquina superior izquierda, por lo que su centro está ubicado en (0.5, 0.5).

Tiene que ver con antialiasing: si "dibuja" un píxel negro en (1,1), 4 píxeles grises se pintarán de gris, entre (0,0) y (2,2). Lea más sobre esto en C++ GUI programming with Qt 4.

11

Gracias MiKy. También encontré una explicación en:

https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Applying_styles_and_colors#A_lineWidth_example

Este es el contenido relevante:

La obtención de líneas nítidas requiere la comprensión de cómo se trazan caminos. En las imágenes a continuación, la cuadrícula representa la cuadrícula de coordenadas del lienzo. Los cuadrados entre líneas de cuadrícula son píxeles reales en pantalla. En la primera imagen de cuadrícula a continuación, se rellena un rectángulo de (2,1) a (5,5). La totalidad de área entre ellos (rojo claro) cae en los límites de píxeles, por lo que el resultado rectángulo relleno tendrá bordes nítidos.

Crisp and Blurry lines example

Si se tiene en cuenta un camino a partir de (3,1) a (3,5) con un grosor de línea de 1.0, se termina con la situación en la segunda imagen. El área real que se va a rellenar (azul oscuro) solo se extiende hasta la mitad de los píxeles en a ambos lados de la ruta. Una aproximación de esto tiene que ser prestados, lo que significa que esos píxeles solamente siendo sombreados parcialmente, y los resultados en toda la zona (la luz azul y azul oscuro) siendo rellenado con un color sólo la mitad tan oscuro como la carrera real color. Esto es lo que ocurre con con la línea de ancho 1.0 en el código de ejemplo anterior.

Para solucionar este problema, tiene que ser muy preciso en su creación camino. Sabiendo que una línea de anchura 1,0 extenderá medio de una unidad a cada lado de la trayectoria, la creación de la trayectoria a partir de (3.5,1) a (3.5,5) resulta en la situación en los extremos ancho de la imagen-La tercera línea 1.0 completamente y llenando con precisión una línea vertical de un solo píxel.

+0

+1 - El enlace tiene la mejor explicación, con algunos buenos diagramas. – Castrohenge

+0

Este enlace explica el problema y la solución. –

+0

El enlace ahora está roto – streppel

2

En pocas palabras, los píxeles no se pueden dividir. Cuando utiliza lineTo para dibujar una línea de 1 píxel, la línea se centra en la coordenada que especifique. Si width = 1 y la coordenada es un entero, entonces está pidiendo dibujar 2 mitades de un píxel.

Dado que no puede activar medio píxel, la biblioteca redondea al píxel divisible más cercano a cada lado.

0

Peleo más o menos con eso cuando empiezo después de un tiempo usando el lienzo - estás trabajando con líneas "matemáticas" y no líneas en la pantalla.

Como otros mencionado - una línea a partir de (1,1) a (1,10) comienza entre pixeles (0/0, 1/1) y termina entre (0/10, 1/11)

por lo que es 1 píxel a ancho y 1 píxel a alto. pero agradablemente un poco más ligero ...

Mi solución, si está utilizando el lienzo para dibujar solo "enteros enteros - líneas", p. para crear un control, es usar transform(1,0,0,1,0.5,0.5) (o transform(1,0,0,1,-0.5,-0.5) depende si desea iniciarlo con 0 o 1)

(utilizo la función de transformación para asegurarme de que no haya una (a) o (d) haciendo nuevamente mi vida dura)

acaba de cambiar de puesto a cero en la línea "entre 0 y 1" (ahora se sabe que mi apodo ...)

Esto funciona bien en todos mis casos en los que estoy dibujando (o que dibujar) "pixeled"

Cuestiones relacionadas