Crear un canvas adaptativo

facebook-svg gplus-svg twitter-svg

Tenemos que decirlo alto y claro: El <canvas> ( HTML5 ) no es un elemento que se adapte fácilmente a los diferentes tamaños de pantalla. No es "responsive". LasĀ  dimensiones del <canvas> vienen especificadas en pixeles en el HTML.

<canvas id= "Canvas1" width="250" height="220">Su navegador no soporta canvas :( </canvas>

Redimensionar el canvas con CSS

Podemos redimensionar el <canvas> con CSS pero esto sería como una imagen redimensionada.

En el siguiente ejemplo los dos <canvas> son iguales, con la única diferencia que el <canvas> de la derecha está redimensionado con CSS. Al cambiar tamaño de la ventana se puede apreciar claramente que el segundo <canvas> cambia de tamaño, pero sigue teniendo el mismo número de pixeles.

Su navegador no soporta canvas :(
Su navegador no soporta canvas :(
Su navegador no soporta canvas :(
Su navegador no soporta canvas :(

.contenedor{
  box-sizing:border-box;
  float:left;
  width:50%;
  padding:10px;
}
.lienzo{ 
  border:1px solid #d9d9d9;  
}
#lienzo1{float:right;}
#lienzo2{width:50%;float:left;}

   var canvasP = document.createElement("canvas");
 
      var ctxP = canvasP.getContext("2d");
         if (ctxP) {
             // creamos el patrón.
            ctxP.canvas.width = 20;
            ctxP.canvas.height = 20;   
            ctxP.rect(0, 0, 10, 10);
            ctxP.rect(10, 10, 20, 20);
            ctxP.fillStyle = "#d9d9d9";
            ctxP.fillRect(0, 0, 10, 10);
            ctxP.fillRect(10, 10, 20, 20);
            }
			
      var canvas = document.getElementsByClassName("lienzo"); 
      var ctx;
      for( var i = 0; i < canvas.length; i++){
      if (canvas[i] && canvas[i].getContext) {
      ctx = canvas[i].getContext("2d");
         if (ctx) {console.log("Habemus context")
            ctx.restore();
            // aplicamos el patrón
            ctx.fillStyle = ctx.createPattern(canvasP,"repeat");
            ctx.fillRect(0,0, canvas[i].width, canvas[i].height);
            ctx.save();   
         }
      }
   }

Redimensionar el canvas con JavaScript

En este caso queremos cambiar el tamaño del <canvas> de manera programática, utilizando JavaScript. Para esto en el HTML no especificamos las dimensiones del lienzo.


Su navegador no soporta canvas :(

En el CSS damos al <canvas> una altura y una anchura de 100%, y al <div> que lo contiene le damos width=50%. Se trata de 50% del <article> en este caso. Al redimensionar la ventana, el <canvas> también cambia de tamaño.

#div{ width:50%; height:80%; margin:0 auto;}
#canvas{border:1px solid #d9d9d9; width: 100%; height: 100%;}

Queremos dibujar un circulo en el <canvas> y queremos que sea "responsive", que cambie de tamaño con el <canvas>.

La idea principal

Cada vez que la ventana cambia de tamaño, JavaScript calcula las nuevas dimensiones del <canvas>, y dibuja el circulo en base a estas dimensiones. Lo hace llamando la función inicializarCanvas().

setTimeout(function() {
  inicializarCanvas();
  addEventListener("resize", inicializarCanvas);
}, 15);
Cómo lo hace

El método getComputedStyle() devuelve un objeto ( CSSStyleDeclaration ) con todos los estilos computados del elemento. Utilizamos este método para calcular la anchura y la altura del <canvas> redimensionado.

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

La anchura y la altura del <canvas> vienen en pixeles así que tenemos que extraer el valor numérico.

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

A continuación calculamos las coordenadas del centro del circulo ( X, Y ) y el radio ( r ) utilizando la anchura ( W ) y la altura ( H ) calculadas. Utilizamos Math.floor para deshacernos de los decimales.

X = Math.floor(W/2);
Y = Math.floor(H/2);
r = Math.floor(W/3);

Y finalmente dibujamos en el <canvas>

dibujarEnElCanvas(ctx);
function inicializarCanvas(){
	   if (canvas && canvas.getContext) {
	   var ctx = canvas.getContext("2d");
	   if (ctx) {
		   // calcula la anchura y la altura del canvas
		   var s = getComputedStyle(canvas);
		   var w = s.width;
		   var h = s.height;
		   // extrae el valor numerico            
		   W = canvas.width = w.split("px")[0];
		   H = canvas.height = h.split("px")[0];
		   // calcula las coordenadas del centro y el radio      
		   X = Math.floor(W/2);
		   Y = Math.floor(H/2);
		   r = Math.floor(W/3);
		   // dibuja el circulo en el canvas      
		   dibujarEnElCanvas(ctx);
	   	}
	  }
}

La función dibujarEnElCanvas() es una función que tenemos que escribir:

function dibujarEnElCanvas(ctx){
  ctx.strokeStyle = "#006400";
  ctx.fillStyle = "#6ab155";
  ctx.lineWidth = 5;
  ctx.arc(X,Y,r,0,2*Math.PI);
  ctx.fill();
  ctx.stroke();
}

Ahora lo ponemos todo junto


var canvas = document.querySelector("#canvas");
var X,Y,W,H,r;              
canvas.height = 250; 
function inicializarCanvas(){ 
  if (canvas && canvas.getContext) {
    var ctx = canvas.getContext("2d");
        if (ctx) {
			 var s = getComputedStyle(canvas);
			 var w = s.width;
			 var h = s.height;
					
			 W = canvas.width = w.split("px")[0];
			 H = canvas.height = h.split("px")[0];
			 
			 X = Math.floor(W/2);
			 Y = Math.floor(H/2);
			 r = Math.floor(W/3);
			   
			 dibujarEnElCanvas(ctx);
			 }
		}
	}
	  	   
function dibujarEnElCanvas(ctx){
  ctx.strokeStyle = "#006400";
  ctx.fillStyle = "#6ab155";
  ctx.lineWidth = 5;
  ctx.arc(X,Y,r,0,2*Math.PI);
  ctx.fill();
  ctx.stroke();
}
        

setTimeout(function() {
  inicializarCanvas();
  addEventListener("resize", inicializarCanvas);
  }, 15);

Al redimensionar la ventana tanto el <canvas> como el circulo dibujado dentro cambia de tamaño. El borde queda siempre de 5px ( ctx.lineWidth = 5 ) como establecido en la función dibujarEnElCanvas().

Su navegador no soporta canvas :(