Biblioteca Vis.js

Hace un par de meses estuve investigando como dibujar nodos que tuvieran relación entre sí con una flecha o un conector en un lienzo HTML, estuve buscando como pintar un árbol binario en "cambas" pero me di cuenta que era muy difícil hacer las conexión entre cada uno de los nodos.
Luego decidí que era mejor buscar algún tipo de biblioteca que hiciera lo que yo estaba construyendo y no tratar de reinventar la rueda.
En una de las búsquedas que realice en google encontré esta estupenda biblioteca vis.js, en realidad es una de las herramientas mas fáciles de entender y de utilizar, (al menos en lo que es la sección de las network) es por eso que el día de hoy me he animado a realizar mi primer blog sobre la biblioteca vis.js.

La biblioteca está diseñada para ser fácil de usar, manejar grandes cantidades de datos dinámicos y permitir la manipulación e interacción con los datos.

Network

En este blog nos enfocaremos en la sección de network de la biblioteca Vis.js, la visualización de network funciona sin problemas en cualquier navegador moderno por hasta varios miles de nodos y conectores. Para manejar una mayor cantidad de nodos, la network tiene soporte para clustering. La network usa lienzo HTML para renderizar.

En la documentación de vis.js hay varios ejemplos visuales, los cuales son muy interesantes, pero lastimosamente no te muestra el código de como esta hecho, es por eso que hoy haremos 5 ejemplos para demostrarte algunas funcionalidades de esta estupenda biblioteca.

Lo primero que debemos hacer es descargar la biblioteca aquí. Puedes descargar esta biblioteca de múltiples formas

  1. instalar con npm (recomendado)
  2. npm instala vis
    
  3. instalar con bower
  4. bower instalar vis
    
  5. enlace de cdnjs.com
  6.  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.css">
     <script src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js"></script>
    
  7. Descargar ZIP
  8. V4.21.0
Para realizar nuestros ejemplos utilizaremos la opción tres.

Ejemplo 1:

Haremos un ejemplo básico, creando una red simple con algunos nodos y conectores como se ve en la imagen siguiente:


Empezaremos colocando un div con un id contenedor en el body del html.
<body>
   <div id="contenedor" style="border: 1px solid; width: 600px; height: 600px;" ></div>
</body>
Debajo del div colocaremos  nuestras etiquetas JavaScript, adentro de estas etiquetas empezaremos creando nuestros código para generar la red de la imagen anterior.

Primero crearemos nuestra matriz de nodos con el siguiente código:
<script type="text/javascript">
  // Crear matriz de nodos
  var nodes = new vis.DataSet([
   {id: 1, label: 'Node 1'},
   {id: 2, label: 'Node 2'},
   {id: 3, label: 'Node 3'},
   {id: 4, label: 'Node 4'},
   {id: 5, label: 'Node 5'},
  ]);
</script>
La variable nodes es la que contendrá la matriz de objetos de los nodos que queramos crear, cada nodo esta identificador con la etiqueta id, para dar una pequeña descripción al nodo utilizamos la etiqueta label tal y como se muestra en el código. 

Para crear los conectores también tenemos que hacer una matríz de objetos.
  // Crear matriz de conectores
  var edges = new vis.DataSet([
   {from: 1, to: 2 },
   {from: 1, to: 3 },  
   {from: 2, to: 4 },
   {from: 2, to: 5 },
   {from: 3, to: 3 },
  ]);
La variable edges es la que contendrá el array de objetos de los conectores, la etiqueta from y to son las que le indican al conector de donde debe iniciar y hacia donde debe de terminar, seria como decir "de - a".

Debemos de indicar en que elemento se pintara nuestra red, anteriormente creamos un div con el id contenedor, este sera el contenedor que utilizaremos.
  // crear contenedor de red
  var container = document.getElementById('contenedor');
Declaramos el objeto data, el cual contendrá las matrices de objetos nodes y edges.
  // proporcionar los datos en el formato vis
  var data = {
   nodes: nodes,
   edges: edges
  };
Para pintar nuestra red necesitamos utilizar la función Network de la biblioteca Vis.js
  // aquí se declaran todas las opciones de los nodos y conectores
  var options = {};
  // inicializa la red con las variables como parámetros que ya creamos
  var network = new vis.Network(container, data, options);
En este ejemplo no utilizamos el parámetro options ya que no es necesario, pero en el siguiente te enseñare algunas opciones que podemos utilizar con esta biblioteca.

Código Completo:

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.css">
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js"></script>
 <title>Vis.js</title>
</head>
<body>
 <div id="contenedor" style="border: 1px solid; width: 600px; height: 600px;" >
 </div>
   <script type="text/javascript">
        // crear matriz de nodos
        var nodes = new vis.DataSet([
         {id: 1, label: 'Node 1'},
         {id: 2, label: 'Node 2'},
         {id: 3, label: 'Node 3'},
         {id: 4, label: 'Node 4'},
         {id: 5, label: 'Node 5'},
        ]);

        // crear matriz de conectores
        var edges = new vis.DataSet([
         {from: 1, to: 2 },
         {from: 1, to: 3 },  
         {from: 2, to: 4 },
         {from: 2, to: 5 },
         {from: 3, to: 3 },
        ]);
        
        // crear contenedor de red
        var container = document.getElementById('contenedor');
        
        // proporcionar los datos en el formato vis
        var data = {
         nodes: nodes,
         edges: edges
        };
       
        // aqui se declaran todas las opciones de los nodos y conectores
        var options = {};
       
        //inicializa la red con las variables como parametros que ya creamos
        var network = new vis.Network(container, data, options);
       
    </script>
</body>
</html>

Para los siguientes ejemplos no explicaremos todo desde cero, reutilizaremos el código anterior y modificaremos algunos fragmentos para realizar la demostración.

Ejemplo 2:

Para este ejemplo nos enfocaremos en la forma de los nodos modificando la variable options.

Con esta biblioteca podemos pintar de diferentes formas los nodos de la red.
        var options = {
            nodes: {
                shape: 'star' //box, diamond, database, triangle, circle, square,triangleDown, dot, ellipse
            },
        };
Esta modificación le damos forma de estrella a nuestros nodos de forma general, también podemos utilizar cualquiera de las formas comentadas.

Star
Box
Diamond
Database

 Triangle
Circle
Square
TriangleDown



Dot


Ejemplo 3:

Tambien podemos modificar la forma de los conectores con el siguiente código:
var options = {
            nodes: {
                shape: 'circle'
            },
             edges:{
                arrows: 'to',
            }
        };
Agregando la objeto arrows: 'to'  del objeto edges podemos pintar una punta de flecha en el destino del conector como se muestra en la siguiente imagen:

Si quisieramos colocar una punta de flecha en el inicio del conector únicamente tendremos que colocar from separado por "," como se muestra en el siguiente código:
var options = {
            nodes: {
                shape: 'circle'
            },
             edges:{
                arrows: 'to, from',
            }
        };
También podemos cambiar de color los conectores con el siguiente código:
var options = {
            nodes: {
                shape: 'circle'
            },
             edges:{
                arrows: 'to, from',
                color:{
                    color:'#ff0000',
                },
            }
        };
Ahora haremos que los conectores ya no se representen con una linea continua con el siguiente código:
var options = {
            nodes: {
                shape: 'circle'
            },
             edges:{
                arrows: 'to, from',
                color:{
                    color:'#ff0000',
                },
                dashes:true,
            }
        };

Ejemplo 4:

Veremos algunos ejemplos del objeto layout, con el siguiente código damos dirección a los nodos y conectores:
var options = {
            nodes: {
                shape: 'circle'
            },
            edges:{
                arrows: 'to, from',
                color:{
                    color:'#ff0000',
                },
                dashes:true,
            },
            layout: {
                hierarchical: {
                    direction: 'UD', // UD, DU, LR, RL
                },
            }
        };
Con el objeto direction le indicamos al layout que diera a los nodos una dirección de arriba hacia abajo con el valor "UD" podemos usar cualquiera de los valores comentados para dar una dirección a los nodos. Si queremos mostrar los nodos con una dirección y ordenados por id de menor a mayor, basta solo con utilizar el objeto sortMethod.
var options = {
            nodes: {
                shape: 'circle'
            },
            edges:{
                arrows: 'to, from',
                color:{
                    color:'#ff0000',
                },
                dashes:true,
            },
            layout: {
                hierarchical: {
                    direction: 'UD', // UD, DU, LR, RL
                    sortMethod: 'directed'   // hubsize, directed
                },
            }
        };

Ejemplo 5:

Como pudiste ver, hemos estado dando estilo a los nodos y conectores de forma general, sin embargo, también podemos dar estilo a cada uno de los nodos y conectores, lo único que tenemos que hacer es pasar los objetos en la matriz de nodos y conectores, te lo muestro con el siguiente ejemplo.
<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.css">
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js"></script>
 <title>Vis.js</title>
</head>
<body>
 <div id="contenedor" style="border: 1px solid; width: 600px; height: 600px;" >
 </div>
   <script type="text/javascript">
        // crear matriz de nodos
        var nodes = new vis.DataSet([
         {id: 1, label: 'Node 1', shape: 'star'},
         {id: 2, label: 'Node 2', color: {background:'#00cc44'}},
         {id: 3, label: 'Node 3'},
         {id: 4, label: 'Node 4'},
         {id: 5, label: 'Node 5'},
        ]);

        // crear matriz de conectores
        var edges = new vis.DataSet([
         {from: 1, to: 2 },
         {from: 1, to: 3,color:{color:'#ff0000'}  },  
         {from: 2, to: 4, dashes:false },
         {from: 2, to: 5, color:{color:  '#c6538c'} },
         {from: 3, to: 3 },
        ]);
        
        // crear contenedor de red
        var container = document.getElementById('contenedor');
        
        // proporcionar los datos en el formato vis
        var data = {
         nodes: nodes,
         edges: edges
        };
       
        // aqui se declaran todas las opciones de los nodos y conectores
        var options = {
            nodes: {
                shape: 'circle'
            },
            edges:{
                arrows: 'to',
                color:{
                    color:'#ff0000',
                },
                dashes:true,
            },
            layout: {
                hierarchical: {
                    direction: 'LR', // UD, DU, LR, RL
                    sortMethod: 'directed'   // hubsize, directed
                },
            }
        };
        //inicializa la red con las variables como parametros que ya creamos
        var network = new vis.Network(container, data, options);
       
    </script>
</body>
</html>
Estos 5 ejemplos en realidad son muy básicos, pero espero y te hayan sido útiles, recuerda dejar tus comentarios y compartir el post si te ha gustado.


Para el próximo post, realizaremos un programa que tenga el funcionamiento de la metodología de la ruta crítica, utilizando la biblioteca Vis.js, php y un poco de bases de datos.

Comentarios