Programación en castellano
Inicio > Tutoriales > Generar gráficos utilizando la librería GD
-Tutoriales

Generar gráficos utilizando la librería GD


Generación de gráficos

Generalmente la forma más común de comparación de datos son las tablas y los gráficos. La comparación de datos en un gráfico permite, sin duda, una interpretación más sencilla. Es difícil imaginarse una mejor manera de visualización de gran cantidad de datos y diferentes tipos de dependencias (por ejemplo, la modelación de los cursos de divisas) que diagramas generados dinámicamente. En nuestro caso, nos ocuparemos de la creación de un diagrama de barras.

En el Listado 5 se muestra una clase que permite crear diagramas a partir de los datos colocados en una tabla. Luego mostraremos cómo se puede extender para que los diagramas tengan una presentación más interesante.

Iniciaremos la creación de la clase Chart definiéndole sus atributos:

  • image – identificador de la imagen,
  • width, height – tamaños del gráfico resultante,
  • margin_x, margin_y – márgenes,
  • _x_min, _x_max, _y_min, _y_max – limitación del espacio para el gráfico,
  • _range_w, _range_h – ancho y altura del espacio para el gráfico.
Listado 5: Archivo Chart.class.php
<?php
class Chart {
    var $image; //identicador de la imagen
    var $title = 'Chart'; //título del diagrama
    var $width = 800; //ancho de la imagen resultante
    var $height = 600; //altura de la imagen resultante
    var $margin_x = 40; //margen horizontal
    var $margin_y = 40; //margen vertical
    var $bar_w = 0.8;    //relación del ancho de la columna a
                        //la distancia entre ellas
    var $bar_color = Array(100, 160, 200); //color de las columnas
    var $text_color = Array(0, 0, 0); //color del texto
    var $grid_color = Array(240, 240, 200); //color de la cuadrícula

    var $_x_min; //valor mínimo de x del espacio para el diagrama
    var $_x_max; //valor máximo de x del espacio para el diagrama
    var $_y_min; //valor mínimo de y del espacio para el diagrama
    var $_y_max; //valor máximo de y del espacio para el diagrama
    var $_range_w; //ancho del espacio para el diagrama
    var $_range_h; //altura del espacio para el diagrama

    /**
     * Método draw – genera la imagen
     * como argumento recibe la tabla de valores
     */
    function draw($series) {
        //generamos la imagen cuya altura y ancho son definidos
        $this->image = imagecreate($this->width, $this->height);
        //asignamos el color de fondo
        $this->translateColor();
        //definimos el espacio para la imagen
        $this->calcRange($series);
        //dibujamos la cuadrícula
        $this->drawGrid();
        //colocamos los valores consecutivos en el diagrama
        foreach($series as $x=>$y) {
            $this->setValue($x, $y);
        }
        //colocamos el título del diagrama
        imagestring($this->image, 5, $this->margin_x/2, $this->margin_y/2,
          $this->title, $this->translateColor($this->text_color));
        header("Content-type: image/png");
        imagepng($this->image);
        imagedestroy($this->image);
        exit;
    }

    /**
     * Método drawGrid – dibuja la cuadrícula sobre la imagen
     * su parámetro puede ser la distancia entre las líneas consecutivas
     */
    function drawGrid($size = 20) {
        $y = $size*round($this->_y_min/$size) - $size;
        while($y < ($this->_y_max + $size)) {
            //calculamos los valores consecutivos de y
            $y0 = $this->translateCoordY($y);
            //dibujamos las líneas horizontales
            imageline($this->image, 0, $y0, $this->width, $y0,
              $this->translateColor($this->grid_color));
            $y += $size;
        }
    }

    /**
     * Método setValue – dibuja un rectángulo con base en los parámetros recibidos
     * los parámetros son los valores  x y y
     */
    function setValue($x, $y) {
        //definimos todas las coordenadas del rectángulo de ancho de bar_w
        $p = Array(
            ($x-$this->bar_w/2), $y,
            ($x+$this->bar_w/2), $y,
            ($x+$this->bar_w/2), 0,
            ($x-$this->bar_w/2), 0
        );
        //Las convertimos a coordenadas de la imagen
        $r = $this->translatePoly($p);
        //dibujamos el rectángulo
        imagefilledpolygon($this->image, $r, sizeof($r)/2,
          $this->translateColor($this->bar_color));
    }

    /**
     * Método calcRange – define el espacio para la gráfica
     * su parámetro es la tabla de valores
     */
    function calcRange($series) {
        //comenzamos en el inicio de las coordenadas polares
        $this->_x_min = 0; $this->_y_min = 0;
        $this->_x_max = 1; $this->_y_max = 1;
        foreach($series as $x=>$y) {
            //cambiamos el rango dependiendo del valor
            if($x >= $this->_x_max) $this->_x_max = $x;
            if($x < $this->_x_min) $this->_x_min = $x;
            if($y >= $this->_y_max) $this->_y_max = $y;
            if($y < $this->_y_min) $this->_y_min = $y;
        }
        //definimos el ancho y la altura del diagrama
        $this->_range_w = $this->_x_max-$this->_x_min;
        $this->_range_h = $this->_y_max-$this->_y_min;
    }

    /**
     * Método translatePoly – proyecta los puntos del espacio del diagrama
     * al area de la imagen su parámetro es la tabla con los puntos x, y
     * consecutivos
     */
    function translatePoly($p) {
        $r = Array();
        for($i=0; $i<sizeof($p); $i+=2) {
            //convertimos los puntos consecutivamente
            $r[] = $this->translateCoordX($p[$i]);
            $r[] = $this->translateCoordY($p[$i+1]);
        }
        return $r;
    }

    /**
     * Métodos translateCoordX y translateCoordY – transforman las coordenadas
     * del diagrama su parámetro es el valor x y y correspondientemente
     * el método devuelve el valor de la coordenada para el área de la imagen
     */
    function translateCoordX($x) {
        return round($this->margin_x+($this->width-2*$this->margin_x)*
          ($x-$this->_x_min)/$this->_range_w);
    }
    function translateCoordY($y) {
        return round($this->margin_y-($this->height-2*$this->margin_y)*
          ($y-$this->_y_max)/$this->_range_h);
    }

    /**
     * Método translateColor – permite obtener el identificador del color
     * su parámetro es la tabla de colores RGB
     * el método devuelve el identificador del color
     */
    function translateColor($rgb = Array(255, 255, 255)) {
        return imagecolorallocate($this->image, $rgb[0], $rgb[1], $rgb[2]);
    }

}
?>

El método principal es el draw(), cuya invocación permitirá generar el gráfico. El parámetro de la invocación es la tabla que contiene la serie de datos para presentar. Para colocar adecuadamente los valores en el diagrama crearemos el método que determina su rango calcRange() y los métodos - translateCoordX() y translateCoordY() - que permitirán proyectar los puntos del espacio del diagrama al espacio definido de la imagen resultante. Estas acciones garantizarán la presentación de la serie de datos en el lugar adecuado, sin necesidad de adaptarlos de antemano.

El método setValue() servirá para colocar un valor determinado en el diagrama dibujando una barra de altura determinada. Para seleccionar el color utilizaremos el método translateColor(), que será responsable de su asignación.

En el Listado 6 (chart.php) se mostró un ejemplo del uso de la clase Chart, y su efecto fue visualizado en la Figura 3. En el ejemplo se creó el objeto Chart, luego se rellenó la tabla de datos con valores aleatorios en el rango (-200, 200). El diagrama fue dibujado llamando al método draw().

Listado 6: Archivo chart.php
<?php
require('Chart.class.php');

//cantidad de valores
$count = 32;
//objeto Chart
$chart = new Chart();
//creamos una tabla con
//valores aleatorios
$array = Array();
for($i=0; $i<$count; $i++) {
   $array[] = rand(-200, 200);
}
//colocamos los valores y
//generamos la imagen
$chart->draw($array);
?>
Figura 3: Efecto del funcionamiento del script chart.php

También podemos utilizar la clase Chart de una manera mucho más efectiva y dibujar un diagrama similar pero mucho más complejo – véase el Listado 7. El efecto del funcionamiento del script chart2.php se puede apreciar en la Figura 4.

Figura 4: Efecto del funcionamiento del script chart2.php
Listado 7: Archivo chart2.php
<?php
require('Chart.class.php');

class CChart extends Chart {
var $shadow_color = Array(0, 0, 0); // color de la sombra
var $shadow_size = 2; //desplazamiento de la sombra

//Método setValue – dibuja un rectángulo con base en los valores proporcionados
//los parámetros son los valores  x y y
function setValue($x, $y) {

    //definimos todas las coordenadas del rectángulo
    $x0 = $this->translateCoordX($x-$this->bar_w/2);
    $y0 = $this->translateCoordY($y);
    $x1 = $this->translateCoordX($x+$this->bar_w/2);
    $y1 = $this->translateCoordY(0);

    //desplazamos las coordenadas para obtener el efecto de sombra
    $r = Array(
        $x0+$this->shadow_size, $y0+$this->shadow_size,
        $x0+$this->shadow_size, $y1,
        $x1+$this->shadow_size, $y1,
        $x1+$this->shadow_size, $y0+$this->shadow_size
    );
    //dibujamos la sombra
    imagefilledpolygon($this->image, $r, sizeof($r)/2,
      $this->translateColor($this->shadow_color));

    //definimos el color que depende de la posición en el eje y cuya claridad depende del valor
    if($y < 0) {
        $bar_color_id = $this->translateColor(Array(170, 255, 0),
          1-$y/$this->_y_min);
    } else
    {
        $bar_color_id = $this->translateColor(Array(0, 135, 200),
          1-$y/$this->_y_max);
    }
    $r = Array($x0, $y0, $x0, $y1, $x1, $y1, $x1, $y0);
    //dibujamos el rectángulo sólido
    imagefilledpolygon($this->image, $r, sizeof($r)/2, $bar_color_id);
    //dibujamos el marco sobre el rectángulo
    imagepolygon($this->image, $r, sizeof($r)/2,
      $this->translateColor($this->shadow_color));

    //describimos el valor tomando en consideración su posición
    if($y < 0) {
        imagestring($this->image, 0, $x0, $y0+4, $y,
          $this->translateColor($this->text_color));
    } else
    {
        imagestring($this->image, 0, $x0, $y0-10, $y,
          $this->translateColor($this->text_color));
    }

}
//Método translateColor – permite obtener el identificador correspondiente del color aclarado,
//el parámetro es la tabla de los componente RGB  del color y el nivel de claridad del color
//el método devuelve el identicador del color
function translateColor($rgb = Array(255, 255, 255), $p=0) {
    if($p>255) {
        $p = 255;
    } else
    if($p<0) {
        $p = 0;
    }
    //enumeramos los valores de los componentes del color
    $r = round($rgb[0]+(255-$rgb[0])*$p);
    $g = round($rgb[1]+(255-$rgb[1])*$p);
    $b = round($rgb[2]+(255-$rgb[2])*$p);
    return imagecolorallocate($this->image, $r, $g, $b);
}

}

//número de valores
$count = 32;
//objeto Chart
$chart = new CChart();
//creamos la tabla de los valores aleatorios consecutivos
$array = Array();
for($i=0; $i<$count; $i++) {
$array[] = rand(-200, 200);
}
//colocamos los valores y generamos la imagen
$chart->draw($array);
?>

En el archivo chart2.php aumentamos la clase Chart sobrecargando los métodos setValue() y translateColor(). En este caso, para unos mejores efectos de visualización, nos serviremos de sombras y de diferentes niveles de claridad de los colores. Las barras las dibujaremos con marcos para que sean más distinguibles.

. Métodos de la clase Chart

Método draw()
Como ya se mencionó con anterioridad, el parámetro de invocación de este método es una serie de datos: tabla de valores. Para empezar, creamos la imagen de ancho width y altura height. Seleccionamos un color, éste será el color del fondo de la imagen, translateColor(), nota: ejecutando este método sin parámetros recibiríamos el color blanco. Luego asignamos el espacio para el diagrama: método calcRange(). La cuadrícula será dibujada llamando al método drawGrid(). Las barras que representan los valores son dibujadas invocando el método setValue() dentro de un bucle, sus parámetros son la llave y el valor de los elementos de la tabla de datos. Luego se coloca el título del diagrama con un color dado. Para terminar se envía el encabezado y se genera la imagen para visualizar. Antes de terminar el script, se libera el espacio de memoria ocupado por la imagen.
Método calcRange()
Este método permite seleccionar el rango de datos. Dado que el espacio del diagrama no puede estar vacío, iniciamos definiendo un campo de tamaño 1 por 1. En el bucle analizamos los valores consecutivos y de acuerdo a ellos ampliamos ese espacio. Después de obtener los valores mínimos y máximos, definimos el ancho y la altura de ese espacio.
Método translateCoordX() y translateCoordY()
Estos métodos son usados para definir las coordenadas del pixel en la imagen para el elemento dado en la tabla de datos, es decir, para la llave y el valor dado recibimos respectivamente las coordenadas x y y del punto. De esta manera podemos proyectar los puntos del espacio del diagrama a un espacio limitado de la imagen. Además tomamos en cuenta los márgenes asignados a la imagen.
Método translatePoly()
Es un método auxiliar que permite realizar la proyección de muchos puntos consecutivos al espacio de la imagen. Los valores x y y del primer punto son el primer y el segundo elemento de la tabla, el tercer y el cuarto elemento son las coordenadas del siguiente punto, etc... El método fue introducido para dibujar polígonos (imagepolygon() e imagefilledpolygon()), donde se utilizaba un acuerdo idéntico de almacenamiento de las coordenadas de los puntos.
Método translateColor()
Su parámetro al ser invocado es una tabla de tres elementos, es decir, los elementos del color: R (rojo), G (verde), B (azul). Devuelve el identificador correspondiente del color.
Método drawGrid()
El parámetro opcional de invocación de este método, es el valor que indica cada cuántas líneas hay que colocar una línea horizontal. Las líneas son colocadas en un bucle de tal manera que la primera se encuentre debajo del valor mínimo de la barra y la última por encima de la barra de mayor valor. Desde luego, entre ellas debe haber una línea que corresponde al eje horizontal del diagrama. Las líneas abarcan todo el ancho de la imagen.
Método setValue()
Es el método responsable de dibujar barras que corresponden a los valores consecutivos del diagrama. La barra es un rectángulo cuyo ancho esta definido por el atributo bar_w. La posición x y el nivel y dependen de la llave y del valor del elemento de la tabla que contiene una serie de datos. Las coordenadas definidas se proyectan al espacio de la imagen, luego se coloca el polígono, en nuestro caso, un rectángulo.

. Extensión de la clase Chart – CChart

La clase CChart es la extensión de la clase Chart que consiste en la variación en la manera de colocar las barras, añadiendo el cambio del color dependiendo del valor que se le asigna. Aquí se sobrecargó los métodos setValue() y translateColor(). También se le añadió dos nuevos atributos: shadow_color y shadow_size.

Método translateColor()
El método fue modificado en relación a su primera versión. La diferencia consiste en haber introducido el peso, quedando como segundo parámetro en la invocación del método. El peso define el nivel de claridad del color, donde el valor 1 nos dará el color blanco y el valor 0 no influirá en el color.
Método setValue()
Para empezar, definimos las coordenadas de los puntos que corresponden a los vértices de la barra. Modificándolos de manera adecuada dibujamos el efecto de sombras. Luego, definimos el valor correspondiente del rectángulo tomando en cuenta el valor que le corresponde a la barra. Dependiendo de si el valor es positivo o negativo, seleccionamos uno de los dos colores, lo aclaramos: menos para valores mayores y más para valores menores. Además dibujamos un marco que resaltará los límites de las barras. Para terminar, colocamos, ya sea por encima o por debajo de la barra, el valor en forma numérica.
 
Patrocinados
 

Copyright © 1999-2007 Programación en castellano. Todos los derechos reservados.
Formulario de Contacto - Datos legales - Publicidad

Hospedaje web y servidores dedicados linux por Ferca Network

red internet: musica mp3 | logos y melodias | hospedaje web linux | registro de dominios | servidores dedicados
más internet: comprar | recursos gratis | posicionamiento en buscadores | tienda virtual | gifs animados