Ya he aprendido otra cosa :D

por Áureo Ares

Cómo escalar el contenido de un “canvas” en HTML5 sobre la marcha.

junio 26th, 2014

Cuando trabajas con canvas hay ocasiones en las que no tienes ni idea del tamaño que va a tener el “dibujo”.

Digamos que el contenido de tu canvas va cambiando. Si se hace más grande que el canvas pintarás fuera. Si se hace demasiado pequeño se verá ridículo con todo el espacio disponible alrededor. También puede ocurrir que en lugar de variar el tamaño del dibujo, sea el tamaño del canvas lo que cambie.

Hay técnicas básicas para escalar el contenido del canvas mediante CSS, pero sólo son útiles en casos muy concretos y sencillos.

Yo utilizo un método bastante sencillo pero que funciona muy bien:

  1. Coloco los elementos dentro del canvas con el tamaño que me convenga.
  2. Mantengo una lista de “puntos clave” en el dibujo.
  3. Calculo la escala óptima para que todos los puntos clave quepan dentro del canvas manteniendo el dibujo lo más grande posible.
  4. Aplico la escala al dibujo.
  5. Recoloco el dibujo, pegándolo a la esquina superior izquierda.
  6. Cada vez que haya un cambio en el dibujo (o en el tamaño del canvas) habrá que recalcular la escala y mover de nuevo el dibujo a la esquina si es necesario.

Se este modo el dibujo se ve siempre lo más grande posible.

Es importante tener claro que todos los elementos tendrán una doble representación. Por una parte tendremos las coordenadas y medidas “reales” que manejaremos internamente y por otra parte las que utilicemos para pintarlos al aplicar la escala.

¿Por qué dos medidas diferentes?

Supongamos que tenemos una línea que representa una pared que mide 4 metros. Por comodidad decidimos que vamos a tomar como referencia 1px = 1cm, de modo que tenemos una línea de 400px.

Si va recta desde la esquina superior izquierda hacia la derecha, la línea comenzará en las coordenadas (0/0) y terminará en (400/0). Internamente es mejor guardar las líneas como puntos así que nos guardamos esas dos coordenadas como representación de nuestra “pared”.

Pero el canvas que tenemos para dibujar es muy pequeño, digamos que de 200 x 200 píxeles. La escala a aplicar se ve claramente que es 0,5. Sin embargo, sólo aplicamos la escala en el momento de dibujar la línea, sin modificar las coordenadas reales del elemento.

De este modo conservamos los valores reales para otros usos y al mismo tiempo evitamos arrastrar pequeños errores de redondeo, ya que la escala se aplica siempre sobre el valor original en lugar de sobre valores que ya se han escalado anteriormente.

Los puntos clave.

Lo que suelo hacer es guardarme una lista con la posición de cada uno de los puntos que definen los extremos de los objetos. Los dos extremos de una línea, los vértices de un polígono, las 4 esquinas de una imagen…

Normalmente estos puntos sirven también para otros propósitos. Pero si no los necesito para nada más, otra opción es guardar solamente los puntos más extremos del dibujo ya que son los que usaremos para decidir la escala. En este caso tendremos que estar seguros de mantener los puntos actualizados si los elementos se mueven.

La escala.

La función para calcular la escala dependerá de cómo desarrollemos la aplicación, pero en general es muy fácil.

Tenemos que localizar los “bordes” del dibujo, que vienen a ser los valores máximos y mínimos de las coordenadas X e Y. Son 4 valores que delimitan el dibujo y pueden pertenecer a 4 puntos diferentes (el valor mínimo de X y de Y por ejemplo, no tienen por qué ser del mismo punto):

Ejemplo de puntos que definen los bordes de un dibujo.

Con los 4 valores encontrados, tendremos dos posibles escalas que calcular. El ancho del dibujo viene marcado por la distancia entre los valores mínimo y máximo de X. La relación entre el ancho del canvas y del dibujo nos da la escala óptima para el eje X, y lo mismo sucede con el alto para el eje Y.

Si no es necesario mantener la relación de aspecto en el dibujo podemos directamente aplicar la escala óptima a cada eje, de lo contrario nos quedaremos con la menor y aplicaremos la misma a los dos.

Por último sólo tenemos que mover todo el contenido del canvas para pegarlo a la esquina superior izquierda. Para ello calculamos la distancia entre la esquina superior izquierda (0/0 si no estamos dejando ningún margen) para ambos ejes y la restamos a la posición de todos los elementos.

En el caso de aplicar la misma escala a ambos ejes seguramente nos sobre espacio a un lado del canvas, así que podemos optar por centrar el dibujo en lugar de moverlo completamente a la esquina.

El código:

Podéis ver un ejemplo en el siguiente enlace: Ejemplo de escala en canvas.

Por comodidad está todo el código en la misma página, basta con ver el código fuente desde el navegador o guardarla y abrirla con un editor de texto.