2011-01-31 9 views
7

Mantengo renderizadores paralelos de Flash y HTML5/Canvas para el proyecto OpenHeatMap de código abierto. Estoy plagado de una inconsistencia en la representación de polígonos llenos con coordenadas fraccionales entre las dos versiones. Si renderiza dos polígonos que comparten un borde, Canvas mostrará una unión visible a lo largo de ese borde, mientras que Flash combinará los dos juntos, sin diferencia visible si son del mismo color. He creado una página para mostrar un mínimo de aquí la cuestión:¿Cómo puedo evitar artefactos de costura de borde de polígono en HTML5 Canvas?

http://web.mailana.com/labs/stitchingbug/

[Gak, prevención de spam deja esto de ser una imagen, pero ver aquí para una captura de pantalla web.mailana.com/labs/stitchingbug .png]

la fuente, junto con un proyecto de flash haciendo lo mismo, es aquí:

github.com/petewarden/stitchingbug

la cuestión fundamental es que es imposible hacer cualquier poligonal compleja r endering si no puedes unir polígonos juntos sin costuras. No sé exactamente cuáles son las reglas de relleno de Flash, pero producen los resultados correctos, al igual que los renderizadores 3D. ¿Alguien tiene una solución del lado del cliente para solucionar este problema? Es un navegador cruzado, lo que lo hace parecer deliberado, por lo que también se apreciará cualquier referencia a las reglas utilizadas. Aquí está el código de Canvas:

var ctx = canvas.getContext('2d'); 
    ctx.fillStyle = 'rgb(0,0,0)'; 

    ctx.beginPath() 
    ctx.moveTo(0, 0); 
    ctx.lineTo(50.5, 0); 
    ctx.lineTo(50.5, 100); 
    ctx.lineTo(0, 100); 
    ctx.closePath(); 
    ctx.fill(); 

    ctx.beginPath() 
    ctx.moveTo(50.5, 0); 
    ctx.lineTo(100, 0); 
    ctx.lineTo(100, 100); 
    ctx.lineTo(50.5, 100); 
    ctx.closePath(); 
    ctx.fill(); 
+0

Lluvia de ideas: calcular el centro de cada polígono y en la elaboración de empujar los puntos hacia fuera del centro por una pequeña cantidad (quizás 0.5). Fuerce un ligero sobregiro del anti-aliasing. – Phrogz

+0

Consulte la segunda mitad de [esta respuesta] (http://stackoverflow.com/questions/15631426/svg-fill-not-filling-boundary/15638764#comment22224474_15638764) para comprender por qué simplemente no puede resolver este problema sin un 'hack' 'como un derrame cerebral o relleno insuficiente cuando está involucrado el anti-aliasing. – Phrogz

Respuesta

1

¿Ha considerado truncar todos los códigos de dibujo? No debería reducir la calidad, y podría solucionar su problema.

También podría trazar una línea sobre el área problemática para hacer que el problema sea invisible.

Si falla todo lo demás, debería funcionar.

+1

Desafortunadamente, las coordenadas truncadas solo funcionan en el caso simple de un conjunto estático de polígonos. En cuanto se hace un zoom o se desplaza por un mapa, por ejemplo, el truncamiento causa "bordes danzantes" muy severos cuando se desplazan hacia adelante y hacia atrás entre las coordenadas enteras. También distorsiona notablemente los bordes de polígonos más grandes con pendientes poco profundas. –

3

Esta es una pregunta anterior, pero tuve el mismo problema.

Me parece que dibujar una sola línea entre los dos polígonos (o un contorno alrededor de ellos) resuelve el problema (al menos en Firefox y Chrome).

Eso parece llenar el vacío en Chrome y Firefox por lo menos. Es suficiente para llamar ctx.stroke() después ctx.fill(), o dibujar una sola línea de la siguiente manera:

ctx.beginPath() 
ctx.moveTo(50.5, 0); 
ctx.lineTo(50.5, 100); 
ctx.stroke(); 

y asegúrese de ajustar la strokeStyle por supuesto.

+0

Si la línea que estás acariciando es de un patrón de imagen, en Chrome esto degrada seriamente el rendimiento por alguna razón. – shoosh

+1

Además, esta solución no funciona con polígonos semitransparentes. –

+0

Agregando trazo alrededor del polígono con lineWidth de .5 funcionó bien para mí. Hasta que noté que cuando se acercaron las esquinas del polígono se sobrepasaban dramáticamente. Así que, en cambio, configuro lineWidth a .5/zoom (donde el zoom es 1 para 100%, .5 para 50%, 2 para% 200, etc.) y ahora funciona muy bien. Las polys semitransparentes seguirán apareciendo con bordes notables por desgracia. En teoría, esto podría superarse al hacer que el polígono sea completamente opaco en un lienzo separado y, a continuación, renderizar ese lienzo con transparencia en el lienzo de destino; sin embargo, esto podría generar un impacto significativo en el rendimiento. – CodeAndCats

1

puedo ver el mismo problema en Chrome 41.0.2272.89 m incluso cuando las coordenadas son todos los números enteros: http://jsfiddle.net/xgd03fyb/

var canvas = document.getElementById('myCanvas'); 
var context = canvas.getContext('2d'); 
context.lineWidth = 0; 
context.fillStyle = 'black'; 

context.beginPath(); 
context.moveTo(100, 100); 
context.lineTo(200, 200); 
context.lineTo(200, 100); 
context.closePath(); 
context.fill(); 

context.beginPath(); 
context.moveTo(100, 100); 
context.lineTo(100, 200); 
context.lineTo(200, 200); 
context.closePath(); 
context.fill(); 

sospechaba que el problema podría ser causado por falta de coincidencia hacia la derecha/hacia la izquierda, como en algunas bibliotecas que solía usar en el pasado afectarían los bordes que se dibujan como sólidos, que como transparentes y como antialias. Sin embargo, cambiar el orden de las llamadas lineTo() en el segundo triángulo no parece tener ningún efecto.

También he intentado cambiar el fillStyle (el argumento pasó a fill()) desde "evenodd" desde el valor predeterminado "nonzero", sin suerte.

No está claro para mí a partir de la especificación https://html.spec.whatwg.org/multipage/scripting.html#dom-context-2d-fill cómo debe trabajar por lo que he presentado el error para aprender más: https://www.w3.org/Bugs/Public/show_bug.cgi?id=28217