Comunidad de diseño web y desarrollo en internet

Cómo escalar y redimensionar con proporción un Paper SVG de Raphael.js

Ayer mismo culminó el curso de HTML5 de mejorando.la impartido por @freddier y @cvander en Madrid. Entre los muchos contenidos que se impartieron, se enseñaron los principios básicos de cómo utilizar la útil librería de Javascript Raphaël de la cual ya se ha comentado anteriormente por acá.

Con esta librería podemos dibujar y manipular elementos vectoriales en el navegador utilizando para ello SVG, con la asombrosa característica de que si se está utilizando Internet Explorer 6+ (que no cuenta con soporte para SVG hasta la versión 9) entonces los gráficos se representarán utilizando VML.

En el curso surgió la duda de cómo lograr escalar un Paper de Raphaël de manera correcta. Aunque existe una solución para lograr esto, a mí en particular me ha dado problemas de no escalar bien los elementos en algunas aplicaciones web. Como lo prometido es deuda y les prometí a los participantes del curso que iba a publicar un pequeño tutorial de cómo lograr esto, aquí cumplo mi promesa.

En realidad no se necesita una función muy compleja para lograr nuestro objetivo, sólo con utilizar el atributo viewBox del SVG se puede lograr de manera sencilla. Este atributo se utiliza para hacer un recorte en los gráficos SVG utilizando para ello unas coordenadas iniciales del recorte y el ancho y el alto del mismo.

Utilizar el atributo viewBox directamente en un SVG


La manera de hacerlo directamente en el código del encabezado del SVG es la siguiente:

Código :

<svg version="1.1" id="mySVG" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="100px" height="100px" viewBox="0 0 100 100" xml:space="preserve">
...
...
...
</svg>
En este caso, al tener el documento un viewBox con su mismo tamaño, se escalará proporcionalmente cuando se varíen sus dimensiones sin ocultar ninguna parte del gráfico. Esto mismo es lo que vamos a utilizar en el Paper utilizando un método propio de Raphaël: setViewBox.

Asignar el atributo viewBox al SVG usando Raphaël


La forma de utilizar el método setViewBox es la siguiente:

Código :

Paper.setViewBox(x, y, w, h, fit);
Donde x, y, w, h corresponden respectivamente a las coordenadas x e y de inicio y al ancho y alto del recorte. El parámetro fit determinará si se desea que al gráfico se muestre completamente dentro del borde del recorte (en caso de ser true). Utilizando este método ya nuestro SVG se escalará manteniendo sus proporciones cuando se varíe de tamaño el objeto Paper mediante el método setSize.

Utilización opcional del atributo preserveAspectRatio


También existe un atributo que permite que el gráfico SVG se escale comportándose de manera diferente, nos referimos a preserveAspectRatio. Este atributo puede utilizarse para que el gráfico mantenga sus proporciones o se escale sin mantener su relación de aspecto.

Si este atributo tiene valor none el gráfico no mantendrá su relación de aspecto, los demás valores mantendrán su proporción pero variarán la posición del mismo con respecto al borde definido por el tamaño del SVG. Ponemos algunos ejemplos de valores que puede tomar preserveAspectRatio:


1 - xMidYMin. 2 - xMinYMax. 3 - xMaxYMin

Notar que estos valores están compuestos por la posición que deben ocupar las x y las y del gráfico, los cuales pueden ser Min (Mínimo), Mid (Medio) y Max (Máximo).

Para poder añadir este atributo al SVG debemos acceder al objeto SVGSVGElement directamente, para hacerlo accederemos a la propiedad canvas del Paper.

Código :

paper.canvas.setAttribute("preserveAspectRatio", "xMaxYMin");

Cada vez que se llame al método setSize del objeto Paper, el atributo preserveAspectRatio tomará su valor por defecto: xMinYMin meet o xMinYMin dependiendo de si el parámetro fit del método setViewBox se sitúa en true o false respectivamente, por lo tanto cada vez que se llame a dicho método, se debe volver a añadir el atributo preserveAspectRatio en el valor deseado.


Ejemplo práctico


El poder variar las dimensiones del Paper a nuestra conveniencia variando el tamaño de todos los elementos dibujados en él, nos será muy útil si se desea implementar Responsive Design utilizando gráficos vectoriales. Vamos a ver un pequeño ejemplo donde se le dará a un Paper de Raphaël las dimensiones de un div contenedor y los gráficos contenidos en el mismo se ajustarán a las dimensiones de dicho div.

Fichero CSS

Código :

body, html{
   height: 100%;
   width: 100%;
}

body{
   margin: 0;
   padding: 0;
}

#raphaelContainer {
   height: 100%;
   width: 100%;
}

Fichero HTML

Código :

<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Responsive Raphael Example</title>
<link href="styles/styles.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="scripts/leaves.js"></script>
<script type="text/javascript" src="scripts/raphael-min.js"></script>
<script type="text/javascript">
   
   var drawWidth = 100;
   var drawHeight = 100;
   var paper;
   
   //---Al estar listo el DOM
   window.addEventListener("load", init);
   
   //---Inicizalizar la aplicación
   function init(){
      
      //---Crear el canvas de Rapahel
      paper = Raphael("raphaelContainer", drawWidth, drawHeight);
      
      //---Aplicar el viewBox (esta línea es la que hace que el gráfico se escale proporcionalmente)
      if(Raphael.svg) paper.setViewBox(0, 0, drawWidth, drawHeight, true);
      
      //---Dibujar todos los elementos
      paper.add(leaves);
      
      //---Al iniciar variar el tamaño
      setSize();
      
   }
   
   //---Cambiar las dimensiones del canvas al máximo tamaño
   function setSize(){
      
      //---Dimensiones del container
      var width = document.getElementById("raphaelContainer").offsetWidth;
      var height = document.getElementById("raphaelContainer").offsetHeight;
      
      paper.setSize(width, height);
      
      //---Esta línea es la que varía la propiedad preserveAspectRatio
      //paper.canvas.setAttribute("preserveAspectRatio", "xMedYMin");
      
   }
   
   //---Al variar el tamaño de la ventana
   window.addEventListener("resize", setSize);

</script>
</head>

<body>

   <div id="raphaelContainer">    
   </div>

</body>
</html>
Descargar los ficheros usados en el tutorial

Un saludo y ojalá les sirva de ayuda este pequeño tutorial.

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Publica tu comentario

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate