javascript - Canvas drawImage - bordes visibles de los mosaicos en firefox/opera/ie (no en chrome)
Estoy dibujando un mapa de juego en el lienzo. El suelo está hecho de baldosas: simples imágenes PNG de 64x64.
Cuando lo dibujo en Chrome, se ve bien (izquierda), pero cuando lo dibujo en Firefox/Opera/IE (derecha), obtengo bordes visibles:
El problema desaparece cuando utilizo números redondeados:
ctx.drawImage(img, parseInt(x), parseInt(y), w, h);
Pero eso no ayuda cuando uso el escalado:
ctx.scale(scale); // anything from 0.1 to 2.0
También probé estos, pero no hubo cambios:
ctx.drawImage(img, 5, 5, 50, 50, x, y, w, h); // so not an issue of clampingctx.imageSmoothingEnabled = false;image-rendering: -moz-crisp-edges; (css)
¿Hay alguna manera de hacerlo funcionar en ff/op/ie?
Editar: Se encontró una solución parcial
Agregar 1 píxel al ancho/alto y compensarlo mediante la escala (ancho+1/escala) parece ayudar:
ctx.drawImage(props.img, 0, 0, width + 1/scale, height + 1/scale);
Genera algunos artefactos, pero creo que es aceptable. En esta imagen, puedes ver azulejos verdes sin bordes y ventanas azules, que no están compensadas, todavía con bordes visibles:
Respuesta #1
La solución más simple (y argumentaría que la más efectiva) es usar baldosas que tengan una superposición de 1 píxel (sean 1x1 o 2x2 más grandes) al dibujar las baldosas de fondo de tu juego.
Nada elegante, solo dibuja un poco más de lo que normalmente harías. Esto evita complicaciones y consideraciones de rendimiento al introducir transformaciones adicionales en la mezcla.
Por ejemplo:
var img = new Image();
img.onload = function () {
for (var x = 0.3; x < 200; x += 15) {
for (var y = 0.3; y < 200; y += 15) {
ctx.drawImage(img, 0, 0, 15, 15, x, y, 15, 15);
// If we merely use 16x16 tiles instead,
// this will never happen:
//ctx.drawImage(img, 0, 0, 16, 16, x, y, 16, 16);
}
}
}
img.src = "http://upload.wikimedia.org/wikipedia/en/thumb/0/06/Neptune.jpg/100px-Neptune.jpg";
Antes: http://jsfiddle.net/d9MSV
Y después: http://jsfiddle.net/d9MSV/1/
Nota como señaló la persona que pregunta, el píxel extra necesita tener en cuenta el escalado, por lo que una solución más correcta es su modificación: http://jsfiddle.net/d9MSV/3/
Respuesta #2
Causa
Esto es causado por el anti-aliasing.
El lienzo aún está en desarrollo y los navegadores tienen diferentes implementaciones para manejar el anti-aliasing.
Posibles soluciones
1
Puedes intentar desactivar el suavizado de imágenes en Firefox así:
context.mozImageSmoothingEnabled = false;
En Chrome:
context.webkitImageSmoothingEnabled = false;
y añade una clase al elemento así (debería funcionar con Opera):
canvas {
image-rendering: optimizeSpeed; // Older versions of FF
image-rendering: -moz-crisp-edges; // FF 6.0+
image-rendering: -webkit-optimize-contrast; // Webkit
image-rendering: -o-crisp-edges; // OS X & Windows Opera (12.02+)
image-rendering: optimize-contrast; // Possible future browsers.
-ms-interpolation-mode: nearest-neighbor; // IE
}
Aquí hay una prueba de navegador que hice para ver el efecto de desactivar el anti-aliasing:
PRUEBA DE NAVEGADOR ANTI-ALIAS
2
Traslada todo el lienzo 0,5 puntos.
ctx.translate(0.5, 0.5);
Esto no siempre funciona y podría entrar en conflicto con otras traducciones. Sin embargo, puedes añadir un desplazamiento fijo cada vez:
ctx.translate(scrollX + 0.5, scrollY + 0.5);
3
Otra opción es hacer un compromiso en el que agregues un píxel extra a los azulejos, lo cual no recomiendo debido al trabajo adicional que tendrás al mantener esto.
4
Este método dibuja las fichas un poco escaladas para que se superpongan:
ctx.drawImage(tile, x, y, 65, 65); //source tile = 64x64
Esto podría ser suficiente para cubrir el fallo. Combinado con desactivar el anti-alias (o usar vecino más cercano), no afectará mucho a los gráficos de los mosaicos, pero podría reducir el rendimiento un poco debido al escalado.
Si desactivas el antialiasing (y eso no funcionó por sí solo), la sobrecarga será mínima ya que parte se utiliza para interpolar la imagen.
5
Simplemente dibuja todo con un desplazamiento de -1 posición (es decir, cuadrícula=63x63). Por supuesto, esto arruinará todo lo demás con respecto a las comprobaciones, así que...

