Flot – Una librería gráfica para jQuery

Es sorprendente la cantidad de alternativas para crear gráficos en un sitio web. Cuando empecé a investigar sobre el tema no esperaba encontrar tanto, pero la verdad es que hay opciones para todos los gustos:

Luego de probar Google Chart API (la unica opción de la lista que no requiere JavaScript) y gRaphael decidí quedarme con Flot, una librearía gráfica para jQuery. Gráficos atractivos, sintaxis intuitiva (es como usar cualquier otro plugin de jQuery), soporte para eventos y la posibilidad de ser extendida a través de plugins, son varias de las características que hicieron de esta librería mi elección para crear gráficos para la web.

El siguiente ejemplo muestra como crear un gráfico de líneas usando Flot. El resultado es un gráfico como el que aparece aquí.

Primero prepararemos una página HTML donde dibujar el gráfico. Debemos incluir jQuery, Flot, Navigate (un plugin para Flot) y un archivo con nuestro código JavaScript. El contenido de la página será un elemento DIV donde se va a renderizar el gráfico.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <title>Flot - Una librería gráfica para jQuery - Demo</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <style>
            body {
                font-family: Arial,Helvetica,"Liberation Sans","DejaVu Sans",sans-serif;
                font-size: 12px;
            }
            #graph {
                margin: 50px auto 0;
                width: 960px;
                height: 600px;
            }
            #tooltip {
                position: absolute;
                padding: 4px;
                opacity: 0;
                -moz-border-radius: 4px;
                -webkit-border-radius: 4px;
            }
        </style>
    </head>
    <body>
        <div id="graph"></div>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
        <script src="jquery.flot.min.js"></script>
        <script src="jquery.flot.navigate.min.js"></script>
        <script src="script.js"></script>
     </body>
</html>

Ahora debemos generar los datos del gráfico en un formato apropiado para Flot. Flot acepta multiples series de datos, cada una como un objeto con atributos label y data. label es la etiqueta de la serie y data un array de parejas[x,y]:

var series = [{
    'label': 'Serie 1',
    'data': [[1264377041075, 447], [1264428833413, 1524], [1264455973422, 375]]
}];

Usaremos la siguiente función para generar los datos que se utilizarán en el ejemplo. Los valores en el eje x serán timestamps y los valores en el eje y serán numeros enteros entre 0 y 600.

/* @series: cantidad de series
 * @n: cantidad de datos por serie */
function generateInputData(series, n) {
    var start = (new Date()).getTime(),
        data = [], date, dots, dot,
        maxx = 0, miny = 0, maxy = 0, j;
    for (var i = 0; i < series; i++) {
        date = start; dots = [], j = 0;
        do {
            j++;
            // cantidad aleatoria de milisegundos entre
            // 86400000 (1 día) y 259200000 (3 dias)
            dot = Math.round(Math.random() * 600);
            date += Math.round((Math.random() * 172800) + 86400) * 1000;
            dots.push([date, dot]);
            // guarda los valores extremos
            if (dot > maxy) {
                maxy = dot;
            } else if (dot < miny) {
                miny = dot;
            }
        } while (j < n);
        // guarda el mayor timestamp
        if (date > maxx) { maxx = date; }

        data.push({'label': 'Serie ' + i, 'data': dots});
    }
    return {'data': data, 'minx': start, 'miny': miny, 'maxx': maxx, 'maxy': maxy};
}

El siguiente paso es usar Flot para convertir nuestros datos en un gráfico de lineas interactivo. Primero creamos el gráfico:

var container = $('#graph'),
    tooltip = $('<div id="tooltip"/>').appendTo($('body')),
    series = generateInputData(3, 9),
    plot, point = null,
    // opciones para Flot
    options = {
        series: {
            lines: { show: true },
            points: { show: true },
            sahdowSize: 0
        },
        grid: { hoverable: true, clickable: true },
        legend: {
            show: true,
            position: 'nw'
        },
        xaxis: {
            mode: 'time',
            min: series.minx,
            max: series.maxx,
            zoomRange: [1, series.maxx - series.minx],
            panRange: [series.minx, series.maxx]
        },
        yaxis: {
            min: series.miny,
            max: series.maxy,
            zoomRange: [1, series.maxy - series.miny],
            panRange: [series.miny, series.maxy] },
        zoom: { interactive: true },
        pan: { interactive: true }
    };

// usa Flot para crear el gráfico dentro de #graph
plot = $.plot(container, series.data, options);

La parte importante del fragmento de código anterior es el objeto options y la última linea, donde se crea el gráfico. Es importante notar que ninguna de las opciones definidas es obligatoria, Flot es capaz de generar el gráfico aun si se omite el parametro options. Sin embargo, para lograr el resultado que esperamos en esta ocasión se configuró el plugin como sigue:

  • series indica que se debe mostrar las lineas y los puntos de las series y que no si dibujará sombra.
  • grid habilita los eventos plothover y plotclick que se pueden escuchar en el contenedor del gráfico.
  • xaxis y yaxis permiten configurar parametros de los ejes del gráfico. en este caso se definieron los valores máximos y mínimos, dos parametros para el plugin de navegación y el parametro mode=time para indicar que los valores en el eje x son timestamps.
  • zoomRange y panRange restringen la profundidad del zoom y el area que se puede explorar del gráfico, respectivametne.
  • zoom y pan activan estas opciones del plugin de navegación.

La documentación para el API de Flot (texto en inglés) ofrece mucho mas detalle sobre estas y otras opciones de configuración. Se recomienda leerlas.

Para finalizar, utilizamos el evento plothover para mostrar un tooltip cuando el cursor pasa por alguno de los puntos del gráfico. Así:

// agregar tooltips
container.bind('plothover', function(event, pos, item) {
    // si el cursor está sobre uno de los puntos
    if (item) {
        // comprueba que se trate de un punto diferente al que se le generó
        // tooltip la última vez
        if (point === null || point[0] != item.datapoint[0] || point[1] != item.datapoint[1]) {
            // guarda el punto para evitar generar el mismo tooltip dos
            // veces consecutivas
            point = item.datapoint;
            // Flot permite conocer información sobre el punto para el cual
            // estamos generando el tooltip:
            // - item.series contiene información sobre la serie a la q pertenece
            // el punto. la etiqueta y el color son dos buenos ejemplos.
            // - item.pageX e item.pageY son las coordenadas el punto respecto
            // al documento (coordenadas globales).
            // - pos.pageX y pos.pageY son las coordenadas globales del cursor.
            tooltip.html(item.series.label + ': ' + parseInt(point[1].toFixed(2)))
                   .css('background-color', item.series.color);
            // centra el tooltip sobre el punto
            var x = item.pageX - (tooltip.width() / 2),
                y = item.pageY - tooltip.height() - 18;
            // animación para el tooltip
            if (tooltip.css('opacity') < 0.2) {
                tooltip.stop().css({top: y, left: x}).animate({ opacity: 1}, 400);
            } else {
                tooltip.stop().animate({ opacity: 1, top: y, left: x}, 600);
            }
        }
    } else {
        // si el cursor no está sobre uno de los puntos escondemos el tooltip
        tooltip.stop().animate({opacity: 0}, 400);
        point = null;
    }
});

pos e item, parametros del callback para el evento plothover, ofrecen mas información que la descrita en el código anterior. Se recomienda usar console.log de Firebug para descubrir los secretos que esconde :P.

Así se ve el resultado final.

¿Qué librerias usan ustedes para generar gráficos en la web?

Lea acerca de otras librerías en Graphing/Charting Data on Web Pages: JavaScript Solutions y Using various javascript libraries to create pie chart.

Comments

  1. oms
    November 5, 2010 at 12:07 am

    es genial esta libreria grafica. muchisimas gracias.

    solo tengo una duda. estoy intentando hacer una grafica de una clasificacion, por lo que el punto mas alto corresponde al numero/dato mas bajo. He estado metiendo mano pero no consigo nada….

    hay alguna manera de que la numeracion de los ejes quede acorde a este tipo de grafico???

    1 saludo y de nuevo muchas gracias por el aporte.

    1. pedro picapiedra
      February 18, 2011 at 3:38 pm

      Hola, yo estoy haciendo esactamente lo mismo pero con tiempos, asique me sucede los mismo que a ti, facil su solucion.

      Lo que debes de hacer es insertar numeros negativos, asi el menor valor sera el mas alto, y asi te queda tu menor valor como el mejor en la grafica 🙂

      Luego tu puedes modificar el archivo de como muestra los labels de la grafica, asique le pides que muestre el opuesto al que grafica, osea si te grafica -30, le pides que a la hora de mostrar muestre 30

      Saludos!

  2. Andres623925
    April 11, 2011 at 9:10 pm

    aporte al blog en cuanto a Internet Explorer 8 para que te funciones necesitas de la siguiente linea de código :

    se que funciona con explorer 8 no e probado con inferiores a este, espero a alguien le sirva esta información

  3. Pipo
    July 10, 2012 at 9:18 am

    No veo el código. Podrás incluirlo nuevamente y aclarar un poco donde va la línea..
    gracias

  4. CarlosG
    July 14, 2014 at 7:49 am

    Gracias, yo tambien comence a utilizar flot