lunes, 12 de mayo de 2014

highcharts múltiples series

Este ultimo tiempo he estado trabajando en un proyecto que tiene relación con despliegue de datos de manera gráfica.
Para comenzar el proyecto , no conocíamos librerías js que permitieran la manipulación de dichos datos, comenzamos a probar y encontramos bastantes y buenas, pero ninguna se asemeja al poderío de highcharts.

Highcharts es una librería en javascript que permite realizar infinidad de gráficos,completamente configurables,  y lo mejor de todo liviano (para todo lo que hace). aquí puedes ver algunas demos .

En este caso voy a realizar un ejemplo a modo recordatorio, en el cual utilizaremos  una librería disponible dentro de  de esta que es Highstock.
Quiero dejar un registro ya que he visto bastante info sobre este js , pero no he encontrado aún un ejemplo consistente que te permita enviar los datos desde php a la librería en json  como corresponde, sino, más bien  he visto transformaciones de lo retorna en el controlador (PHP)  en la vista (JS). También he considerado hacer el ejemplos con datos tipo "Datatime"  comúnmente llamado fecha .
Al final del post adjunto el ejemplo funcionando , es ideal que lean los pasos.
Al grano ...

1.- Levantemos nuestra html :

  1. <!DOCTYPE html>
  2. <html>
  3.     <head>
  4.         <title>Ejemplo</title>
  5.         <script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
  6.                 <script src="http://code.highcharts.com/stock/highstock.js"></script>
  7.                 <script src="http://code.highcharts.com/modules/exporting.js"></script>
  8.                
  9.    </head>
  10.   <body>
  11.         <div id="chartContainer" style="width:100%; height: 100%;position: relative;">
  12.         </div>
  13.   </body>
  14. </html>

Utilizaremos  Jquery , es posible encontrar Highcharts para "extjs"   si estás desarrollando en este  FW.
Si prestan atención, verán que hay solo 1 div en el html y que tiene id : chartContainer , este div se utilizará para crear los gráficos.

2.- Creando función :
Seguido agregamos nuestro instancia de Highcharts  dentro de los tags <script></script>  y cuando la el dom este cargada ,lanzaremos nuestro grafico :
    1.           var chart_; // contenedor del retorno de Highcharts
    2.                 $(document).ready(function() {
    3.                 });
    4.                 function CrearGrafico(data){
    5.                 options = {
    6.                         chart : {
    7.                                 renderTo : "chartContainer",
    8.                                 defaultSeriesType : 'column',
    9.                                 plotBackgroundColor : null,
    10.                                 plotBorderWidth : null,
    11.                                 plotShadow : false,
    12.                                 height : 800,
    13.                                 width : 800,
    14.                                 type : 'line',
    15.                         },
    16.                        
    17.                         legend : {
    18.                                 layout : 'vertical',
    19.                                 align : 'right',
    20.                                 verticalAlign : 'middle',
    21.                                 borderWidth : 0
    22.                         },
    23.                         credits : {
    24.                                 enabled : false
    25.                         },
    26.                         scrollbar : {
    27.                                 enabled : true,
    28.                         },
    29.                         navigator : {
    30.                                 enabled : true,
    31.                         },
    32.                         loading: {
    33.                 hideDuration: 1000,
    34.                 showDuration: 1000
    35.                 },
    36.                         rangeSelector : {
    37.                                 enabled : true,
    38.                                 selected : 6,
    39.                         },
    40.                         title : {
    41.                                 text : 'Grafico de <b>Titulo</b>'
    42.                         },
    43.                         subtitle : {
    44.                                 text : 'Grafico de <b><i>Subtitulo</i></b>'
    45.                         },
    46.                         xAxis : {
    47.                                 type : 'datetime',
    48.                                 title : {
    49.                                         enabled : true,
    50.                                         text : ' <b>Periodo</b>',
    51.                                         style : {
    52.                                                 fontWeight : 'normal',
    53.                                         },
    54.                                 showEmpty:true,
    55.                                 },
    56.                         },
    57.                         yAxis : {
    58.                                 title : {
    59.                                         enabled : true,
    60.                                         text : '<i>' + tipoDato + '</i>',
    61.                                         style : {
    62.                                                 fontWeight : 'normal',
    63.                                         },
    64.                                         showEmpty:true,
    65.                                 },
    66.                         },
    67.                         series : data,
    68.                 };
    69.        
    70.                 chart_ = new Highcharts.Chart(options);
    71.                 }
 Deben prestar atención a que he creado una función  que se llama  CrearGrafico(),  esta tiene la configuración del display Highcharts, es bastante intuitiva , de eso solo me voy a referir a que debes siempre declarar un height y width , como en este caso :800x800,para el correcto despliegue.
Esta función recibe un parámetro  "data".
3.- Petición ajax:
 La llamada ajax tiene que retornar valores json , y por el mismo motivo nosotros debemos recibirlos de la misma manera  :
  1. $.getJSON('ajax.php', function(data) {
  2.                                                 CrearGrafico(data);
  3.                         });

 Con esto el html final nos queda de la siguiente manera :

  1. <!DOCTYPE html>
  2. <html>
  3.     <head>
  4.         <title>Ejemplo</title>
  5.         <script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
  6.                 <script src="http://code.highcharts.com/stock/highstock.js"></script>
  7.                 <script src="http://code.highcharts.com/modules/exporting.js"></script>
  8.                 <script>
  9.                         var chart_; // contenedor del retorno de Highcharts
  10.                 $(document).ready(function() {
  11.                         $.getJSON('ajax.php', function(data) {
  12.                                                 CrearGrafico(data);
  13.                         });            
  14.                
  15.                 });
  16.                 function CrearGrafico(data){
  17.                 options = {
  18.                         chart : {
  19.                                 renderTo : "chartContainer",
  20.                                 defaultSeriesType : 'column',
  21.                                 plotBackgroundColor : null,
  22.                                 plotBorderWidth : null,
  23.                                 plotShadow : false,
  24.                                 height : 800,
  25.                                 width : 800,
  26.                                 type : 'line',
  27.                         },
  28.                        
  29.                         legend : {
  30.                                 layout : 'vertical',
  31.                                 align : 'right',
  32.                                 verticalAlign : 'middle',
  33.                                 borderWidth : 0
  34.                         },
  35.                         credits : {
  36.                                 enabled : false
  37.                         },
  38.                         scrollbar : {
  39.                                 enabled : true,
  40.                         },
  41.                         navigator : {
  42.                                 enabled : true,
  43.                         },
  44.                         loading: {
  45.                 hideDuration: 1000,
  46.                 showDuration: 1000
  47.                 },
  48.                         rangeSelector : {
  49.                                 enabled : true,
  50.                                 selected : 6,
  51.                         },
  52.                         title : {
  53.                                 text : 'Grafico de <b>Titulo</b>'
  54.                         },
  55.                         subtitle : {
  56.                                 text : 'Grafico de <b><i>Subtitulo</i></b>'
  57.                         },
  58.                         xAxis : {
  59.                                 type : 'datetime',
  60.                                 title : {
  61.                                         enabled : true,
  62.                                         text : ' <b>Periodo</b>',
  63.                                         style : {
  64.                                                 fontWeight : 'normal',
  65.                                         },
  66.                                 showEmpty:true,
  67.                                 },
  68.                         },
  69.                         yAxis : {
  70.                                 title : {
  71.                                         enabled : true,
  72.                                         text : '<i>Tipo de dato</i>',
  73.                                         style : {
  74.                                                 fontWeight : 'normal',
  75.                                         },
  76.                                         showEmpty:true,
  77.                                 },
  78.                         },
  79.                         series : data,
  80.                 };
  81.                
  82.        
  83.                 chart_ = new Highcharts.Chart(options);
  84.                 }
  85.                 </script>
  86.                
  87.    </head>
  88.   <body>
  89.         <div id="chartContainer" style="width:100%; height: 100%;position: relative;">
  90.         </div>
  91.   </body>
  92. </html>
Deben prestar atención al arreglo series:data , es aquí donde devolvemos el resultado del ajax.

4.- Ahora revisaremos el archivo PHP - Posgresql :
La información que vamos a desplegar va a ser Fecha (x) ,valor(y)   esto va a ser una serie , y cada serie va a tener su propio nombre . con respecto a Y : el valor que retorna la DDBB float y el de Fecha es tu timestamp :
una pequeña muestra :














No entraré en detalles sobre la base de datos , puesto que no se trata de esto el ejemplo.
El código PHP es el siguiente

  1. <?php
  2. $dbconn = pg_connect("host=localhost dbname=base_de_datos user=user password=pass")
  3.     or die('Could not connect: ' . pg_last_error());
  4. function QueryE($query)
  5. {
  6. $result = pg_query($query) or die('Query failed: ' . pg_last_error()); 
  7. return $result;
  8. }
  9. function getSeries($n)
  10. {
  11. $aux;
  12. $aux['name']='Serie:'.$n;
  13. if($n ==1)
  14. $result=QueryE('SELECT medicion_fecha,medicion_valor FROM ws_ejemplo_dinamico2(\'W_073_6_248\',10,\'0\') ws order by ws.medicion_fecha asc');
  15. else if($n==2)
  16. $result=QueryE('SELECT medicion_fecha,medicion_valor FROM ws_ejemplo_dinamico2(\'W_073_15_104\',6,\'0\') ws order by ws.medicion_fecha asc');
  17. else
  18. $result=QueryE('SELECT medicion_fecha,medicion_valor FROM ws_ejemplo_dinamico2(\'W_073_15_294\',6,\'0\') ws order by ws.medicion_fecha asc');
  19. $numrows=pg_numrows($result);
  20.         for($ri = 0; $ri < $numrows; $ri++) {
  21.         $value=pg_fetch_array($result,$ri);
  22.         $fecha=new DateTime($value['medicion_fecha']); //convertimos los datos a tipo DateTime
  23.         $x=(int)$fecha->format('U')*1000; // convertimos los datosUnix Epoch
  24.         $y=round(($value['medicion_valor']),2); //redondeamos el valor
  25.         $aux['data'][]=array($x,$y);
  26.         }
  27.                 return $aux;
  28.         }
  29.        
  30. $result = array();
  31. $rows1=getSeries(1);
  32. $rows2=getSeries(2);
  33. $rows3=getSeries(3);
  34. array_push($result,$rows1);
  35. array_push($result,$rows2);
  36. array_push($result,$rows3);
  37. echo json_encode($result);

Las querys no son relevantes, tener presente que retornan 2 valores (medicion_fecha,medicion_valor) que pueden estar en otro formato o plataforma  : CSV,Excel,Mysql,Sqlserver,etc.
Lo relevante este código es que para que  Highcharts considere los datos como datatime se le debe indicar en la config ,este tipo, del html ( punto 1 linea verde ) y más aún enviar estos datos en tipo "Unix Epoch" (Linea en rojo del archivo PHP)
La magia de enviar los datos en json directamente desde PHP es "array_push"  quien nos permite unir los arrays,   luego de estos  los datos son convertidos a json por la función "json_encode" y son enviados a la vista .

Al final esto nos genera un gráfico :



El ejercicio va a estar disponible en http://molino.twpanel.com/testing/
Adjunto los 2 archivos para mayor comprensión :
https://mega.co.nz/#!bAYBiSBJ!HDVZwLDn8SW0JmjJb1hWy_vvuHWYsO9sveCexU0HkLI