html5 Posts

Tablet nueva, juegos rotos.

Hace pocos días llego por fin mi tableta (una gallaxy tab 2) y como podrán imaginar lo primero que hice fue probar los juegos que he desarrollado y para mi sorpresa varios de ellos no funcionaban correctamente; en algunos se veía un segundo canvas con la misma imagen y en otros el contenido previo no se borraba. Al parecer es un problema ya viejo con clearRect que afecta a android 4.1. Lo primero que se me ocurrió para solucionar el problema fue el viejo truco de re-definir el tamaño del canvas:
[js]canvas.width = canvas.width;[/js]
Ahora si que funcionaban, pero algunas acciones como el arrastrar eran realmente lentas (especialmente al arrastrar y soltar); el problema con este método es que ademas de borrar el contenido del canvas, también restablece su estado (fillStyle, clearStyle, scale, translate, shadowColor….) lo que al parecer influye en el rendimiento (al menos en el gallaxy tab – único dispositivo que tengo para hacer pruebas). Otra de las soluciones sugeridas para eliminar el problema del canvas duplicado que encontré era el quitar el estilo overflow: hidden de todos los elementos padres del canvas, aunque el problema desapareció al igual que en el método anterior el rendimiento era pésimo.

Solución

Hasta el momento la solución con los mejores resultados es la de usar un color solido como fondo para el canvas y al momento de borrar el contenido usar fillRect en lugar de clearRect
[html]<canvas style="background: #fff;"></canvas>[/html]
[js]function clear(ctx) {
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
}[/js]
El aumento en rendimiento es considerable, sobre todo en juegos que requieren arrastrar y soltar (como el solitario). Aun así esta no es una solución definitiva ya que al usar un color solido no es posible apilar canvas para crear capas.

¿Conoces alguna mejor solución? déjala en los comentarios.

Canvas desde cero: primeros pasos

El elemento canvas es una gran herramienta para crear juego, animaciones y manipular imágenes, aun así no todos los navegadores soportan esta etiqueta, por tanto, es necesario contar con alternativas para no dejar de lado a los usuarios de dichos navegadores.

En esta primera parte veremos dos de estas alternativas así como algunas particularidades de la etiqueta canvas.

Compatibilidad

En la actualidad los únicos navegador que no cuentan con soporte para el elemento canvas son Internet Explorer 6, 7 y 8; no obstante existen soluciones (polyfills) que emulan su funcionalidad, entre los que se destacan:

  • excanvas: utiliza VML, una tecnología propietaria de Microsoft similar al svg y no necesita de plugins, pero carece de algunos métodos (getImageData, toDataURL…).
  • flashcanvas: utiliza flash (duh), es mas rápido que excanvas (a mi parecer) y soporta mas características, pero hay que comprar una licencia para poder desarrollar aplicaciones de comerciales.

La etiqueta canvas

El elemento canvas cuenta con una etiqueta de apertura y una de cierre, pero a diferencia de otras etiquetas, su contenido solo es visible en navegadores antiguos (ya que estos ignoran las etiquetas desconocidas) lo cual nos permite mostrar un contenido alternativo a los usuarios de dichos navegadores.

<canvas height="150" id="canvas" width="300">
<!-- contenido a mostrar si el navegador no soporta canvas -->
<img src="/images/imagen-estatica.jpg" />
</canvas>

Otro hecho a destacar es que sus medidas se declaran mediante los atributos width/height y no a través css. al usar css se escala el elemento, así, si el canvas mide 300×150 y cambiamos sus medidas por 600×300 los pixeles “medirán el doble” y la imagen se verá borrosa.

Por ejemplo, los siguientes cuadros se dibujaron en la mismas posición (10, 10) y tienen las mismas medidas (30×30) pero el canvas de la derecha fue escalado 6x usando css.

Note el borde borroso el la segunda imagen 

Detectar soporte

Antes de empezar a usar el canvas necesitamos saber si el navegador siquiera soporta dicho elemento, para esto:

  1. Creamos un elemento canvas y comprobamos si cuenta con el método getContext
  2. De lo contrario verificamos que exista un Polyfill
if (! document.createElement("canvas").getContext || ! window.G_vmlCanvasManager )
alert("Actualize su navegador");

Accediendo desde javascript

Para poder acceder al elemento desde javascript hay esperar que el DOM este listo, para esto puedes utilizar la función ready de jQuery o colocar el script justo antes de </body>.

A continuación obtenemos una referencia al contexto de dibujo del canvas utilizando el método getContext:

var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");

Ahora si podemos empezar a dibujar:

ctx.fillStyle = "red";
ctx.fillRect(50, 50, 30, 20);

Utiliza un navegador moderno para poder ver el ejemplo

TIPS

Antes de poder acceder al contexto del canvas en IE<9 (usando excanvas/FlashCanvas) debemos inicializarlo, para esto, en lugar de usar el método getContext podemos usar la siguiente función:

function getContext(canvas) {
if (! canvas.getContext && window.GV_ContextCanvas) {
G_vmlCanvasManager.init(canvas);
} else {
throw new Error("El navegador no soporta el elemento canvas");
}

return canvas.getContext("2d");
}

Conclusión

Finalizando esta primera parte tenemos todo listo para empezar a trabajar con el canvas. con suerte ahora podrás mostrar contenido alternativo para usuarios con navegadores antiguos, detectar el soporte del elemento canvas ya sea de forma nativa o mediante un polyfill y obtener el contexto de dibujo.

No te pierdas la siguiente parte en la que veremos el sistema de coordenadas y como dibujar formas básicas.

Si te gusto el tutorias compartelo en twitter o subscribete y te avisare cuando esté disponible la siguiente parte.

Canvas desde cero

Si llevas tiempo con ganas de aprender a usar el canvas o quieres refrescar tus conocimientos,
no puedes perderte esta serie de tutoriales que arranca el día de hoy, donde no solo se explicara
como usar x función sino que desarrollaremos programas reales donde podrás aplicar lo aprendido.

y quien es usted para decirme que hacer

Soy un tipo al que le gusta la programación, en especial todo lo relacionado con la web (javascript *¬*)
y desde que conocí el elemento canvas quede fascinado con la idea de poder dibujar en navegador.
si bien no soy un experto y aun sigo aprendiendo, ya llevo tiempo trabajando con este elemento
y he aprendido mucho gracias a la comunidad y esta es mi forma de contribuir en algo.
algunos de los trabajos que he hecho:

P.D.: Si ven que me estoy colgando en la actualización del blog no duden en jalarme las orejas en twitter XD.

jsaw5: Crea rompecabezas personalizados

Ya llevo tiempo sin escribir, y es que en estos días han pasado muchas. Ahora que tengo tiempo libre (ya que estoy desempleado) me puse en la tarea de crear un juego en javascript y HTML5: jsaw5.

Actualización: el demo fue movido a dropbox

En jsaw5 podrán crear, resolver y compartir rompecabezas personalizados con amigos en twitter y facebook. Espero que lo visiten y den sus opiniones, aun debe tener varios errores pero si esperaba a que fuera “perfecto” 
En el proceso de creación agregue algunas mejoras a canvas-event-js las cuales espero hacer disponibles en cuanto pueda.

Ejemplo método find de canvas-event

Varias personas han estado buscando como usar el método find de canvas-event, por lo que dejo un ejemplo de su uso mientras termino la documentación.

Interfaz del programa Kmines

Usando el método find, es posible seleccionar un grupo de objetos y aplicarles un método o manejador de evento. para esto debemos usar un selector como:

  • tipo: Corresponde con el nombre del método usado para crear el objeto (circle, rect, line…).
  • id: Un nombre que podemos dar a un objeto con el fin de diferenciarlo de otros del mismo tipo.

Imagine estar creando un buscaminas, el campo esta lleno con varios rectángulos: unos son minas y otros no. Todos los rectángulos tienen el mismo color, pero solo los rectángulos mina explotan y terminan el juego, mientras los demás aumentan el puntaje del jugador.

Nota Al igual que en css, el símbolo # indica que mina y safe son id.

for (var i = 0; i < 5; i++) {
ce.rect(i*10, 0, 10).setId("mina");
}

for (var i = 0; i < 5; i++) {
ce.rect(i*10; 10; 10).setId("safe");
}

// selector tipo: todos los rectángulos, tanto #mina como #safe
ce.find("rect").attr("fill", "gray");

// selector id: solo rectángulos #mina
ce.find("#mina").click(function(c, e) {
alert("Boom!");
alert("Game Over");
});

// selector id: solo rectángulos #safe
ce.find("#safe").click(function(c, e) {
puntos += 1;
});

Por otro lado el método getAll (solo en repo de github) retorna un array con los objetos que coinciden con el selector:

// encontrar y retornar los objetos rect dibujados hasta el momento
var rects = ce.findAll("rect");
// rects ahora es igual a [Rect, Rect, Rect...]

// obtener el primer circulo dibujado
var first_circle = ce.getAll("circle")[0];

Si tienen dudas o sugerencia pueden dejarlas en los comentarios, prometo tenerlas en cuenta.