Cómo hacer un elemento Canvas (HTML5) Responsivo

Por user Nestor Plasencia Prado
Cómo hacer un elemento Canvas (HTML5) Responsivo

En este tutorial aprenderemos a redimensionar un elemento canvas de forma dinámica en función de las medidas del navegador.

Siguiendo con nuestro contenido sobre API’s de HTML5, hoy aprenderemos a redimensionar un elemento canvas para que se adapte a los diferente tamaños de pantalla.

Si aún no conoces este elemento tenemos dos tutoriales, los cuales te serán de mucha ayuda. Estos son:

  1. Introducción a canvas de HTML5
  2. Animación con canvas de HTML5

PARTE I : Dimensionamiento inicial

Para dimensionar un elemento canvas se declaran las medidas de ancho y alto como atributos en el elemento canvas de HTML. 

Si bien es recomendable que propiedades como width y height se declaren en un archivo de estilos, totalmente separadas del archivo HTML, vamos a dejar claro que los atributos width y height del elemento en HTML pueden tener resultados distintos a las propiedades width y height declaradas en CSS.

Las medidas especificadas como atributos en el elemento HTML representan los píxeles que posee el lienzo o cuadro de dibujo sobre el que se grafica, recordemos que un elemento canvas es un mapa de bits tal como lo es una imagen. 

Las medidas especificadas como propiedades en los estilos CSS, son las medidas con las que se visualiza el elemento en el navegador.

Veamos qué sucede si agregamos las propiedades de width y height en CSS.

#plano {
  width: 300px;
  height: 100px;
}

Aunque se haya nodificado las medidas de visualización a 300x100 píxeles (color azul), internamente el elemento canvas aún posee una grilla de 200x200 píxeles especificadas inicialmente en HTML (color verde).

Hay que tener en cuenta que si no se especifica las medidas en HTML, el elemento asumira unas medidas por defecto de 300x150 píxeles.

PARTE II : Redimensionamiento Responsivo

En el siguiente ejemplo trazaremos un círculo en un canvas cuadrado de 200x200 píxeles. En HTML asignamos los atributos de alto y ancho, además de un id con valor “plano”.

Para que el elemento se visualice centrado, agregamos márgenes automáticos a la derecha e izquierda, en la propiedad margin. El elemento canvas tiene por defecto el valor de “inline” en la propiedad display, esto no le permite ser afectado por la propiedad margin, por tal motivo para el ejemplo utilizaremos "block" como valor de la propiedad display, lo cual permite al elemento ser afectado por la propiedad margin. Además para visualizar el contorno del elemento canvas, asignamos valores a la propiedad border.

#plano {
  margin: 0 auto;
  display: block;
  border: 1px solid #d9d9d9;
}

El círculo se grafica con la siguiente función:

function dibujar(ctx){
  ctx.fillStyle = "#108EFF";
  ctx.arc(X,Y,X,0,2*Math.PI);
  ctx.fill();
}

Para que el círculo tenga su origen en el centro del elemento canvas, las coordenadas X e Y se establecen como la mitad de las medidas de ancho y alto del elemento, tener en cuenta que los valores de canvas.width y canvas.height son las medidas del elemento especificado en HTML.

X=canvas.width/2;
Y=canvas.height/2;

Ademas el radio sera igual a la coordenada X, de esta manera abarcara todo el elemento canvas.


Hasta aquí tenemos un elemento canvas no responsivo, para tener unas medidas de alto y ancho variables y dependientes del tamaño de la pantalla, incluimos la propiedad width dentro de CSS, con un valor de 50%, el alto se redimensiona automáticamente manteniendo la relación de medida de los atributos ancho y alto declarados en HTML.

#plano{
  width: 50%;
  margin: 0 auto;
  display: block;
  border: 1px solid #d9d9d9;
}

Con este pequeño cambio el elemento ahora adopta medidas según el ancho y alto de la pantalla. Todo indicaría que el problema ha sido resuelto, pero lo único que se está haciendo es redimensionar como si fuera un imagen; conservando el mismo número de píxeles en el mapa de bits, esto produce que si el redimensionamiento se hace de una escala menor a una mayor produce un efecto de pixeleado.




Para evitar el efecto de pixeleado, se tiene que alterar no solo los valores de las propiedades de ancho y alto en CSS, sino también los atributos de alto y ancho en HTML.

Para obtener los valores de las propiedades ancho y alto en CSS utilizamos el método getComputedStyle() que devuelve un objeto con todos los estilos del elemento en CSS. Utilizamos este método para calcular el ancho y alto del elemento canvas redimensionado en CSS.

var s = getComputedStyle(canvas);
var w = s.width;
var h = s.height;

El alto y ancho del elemento canvas vienen en píxeles así que tenemos que extraer su valor numérico haciendo uso del método split. Estos valores los asignamos a los valores de canvas.width y canvas.height. Ahora al modificarse responsivamente los valores de las propiedades alto y ancho de CSS también se modificarán los atributos de alto y ancho en HTML modificando el tamaño del mapa de bits del elemento canvas.

canvas.width = w.split('px')[0];
canvas.height = h.split('px')[0];

Ahora se ha eliminado por completo el efecto de pixeleado, ya que el número de píxeles iniciales de HTML cambia su valor con el redimensionamiento. Con esto tenemos un elemento canvas totalmente responsivo.

Si deseas aprender más sobre las funcionalidades del elemento canvas de HTML5 no puedes perderte nuestro curso APIs de HTML5, para llevar tu código al siguiente nivel.

user

Nestor Plasencia Prado

Programmer | Developer | Maker | Robot Designer | Knowmad