Line graph

Add-On Line graph

Informations

Author:Anthony Master
License: FPDF

Description

This script allows to create line-based charts. The method to use is the following:

LineGraph(float w, float h, array data [, string options [, array colors [, int maxVal [, int nbDiv]]]])

w: graph width
h: graph height
data: multidimensional array containing series of data
options: string containing display options
colors: multidimensional array containing line colors; if null or not given, some random colors are used
maxVal: maximum ordinate; if 0 or not given, it is automatically computed
nbDiv: number of vertical divisions (default value: 4)

Source

<?php
/***********************************************************************************************************

This line graph function was developed by Anthony Master

***********************************************************************************************************/

require('fpdf.php');

class PDF_LineGraph extends FPDF {
    function LineGraph($w, $h, $data, $options='', $colors=null, $maxVal=0, $nbDiv=4){
        /*******************************************
        Explain the variables:
        $w = the width of the diagram
        $h = the height of the diagram
        $data = the data for the diagram in the form of a multidimensional array
        $options = the possible formatting options which include:
            'V' = Print Vertical Divider lines
            'H' = Print Horizontal Divider Lines
            'kB' = Print bounding box around the Key (legend)
            'vB' = Print bounding box around the values under the graph
            'gB' = Print bounding box around the graph
            'dB' = Print bounding box around the entire diagram
        $colors = A multidimensional array containing RGB values
        $maxVal = The Maximum Value for the graph vertically
        $nbDiv = The number of vertical Divisions
        *******************************************/
        $this->SetDrawColor(0, 0, 0);
        $this->SetLineWidth(0.2);
        $keys = array_keys($data);
        $ordinateWidth = 10;
        $w -= $ordinateWidth;
        $valX = $this->getX()+$ordinateWidth;
        $valY = $this->getY();
        $margin = 1;
        $titleH = 8;
        $titleW = $w;
        $lineh = 5;
        $keyH = count($data)*$lineh;
        $keyW = $w/5;
        $graphValH = 5;
        $graphValW = $w-$keyW-3*$margin;
        $graphH = $h-(3*$margin)-$graphValH;
        $graphW = $w-(2*$margin)-($keyW+$margin);
        $graphX = $valX+$margin;
        $graphY = $valY+$margin;
        $graphValX = $valX+$margin;
        $graphValY = $valY+2*$margin+$graphH;
        $keyX = $valX+(2*$margin)+$graphW;
        $keyY = $valY+$margin+.5*($h-(2*$margin))-.5*($keyH);
        //draw graph frame border
        if(strstr($options, 'gB')){
            $this->Rect($valX, $valY, $w, $h);
        }
        //draw graph diagram border
        if(strstr($options, 'dB')){
            $this->Rect($valX+$margin, $valY+$margin, $graphW, $graphH);
        }
        //draw key legend border
        if(strstr($options, 'kB')){
            $this->Rect($keyX, $keyY, $keyW, $keyH);
        }
        //draw graph value box
        if(strstr($options, 'vB')){
            $this->Rect($graphValX, $graphValY, $graphValW, $graphValH);
        }
        //define colors
        if($colors===null){
            $safeColors = array(0, 51, 102, 153, 204, 225);
            for($i=0;$i<count($data);$i++){
                $colors[$keys[$i]] = array($safeColors[array_rand($safeColors)], $safeColors[array_rand($safeColors)], $safeColors[array_rand($safeColors)]);
            }
        }
        //form an array with all data values from the multi-demensional $data array
        $ValArray = array();
        foreach($data as $key => $value){
            foreach($data[$key] as $val){
                $ValArray[]=$val;                    
            }
        }
        //define max value
        if($maxVal<ceil(max($ValArray))){
            $maxVal = ceil(max($ValArray));
        }
        //draw horizontal lines
        $vertDivH = $graphH/$nbDiv;
        if(strstr($options, 'H')){
            for($i=0;$i<=$nbDiv;$i++){
                if($i<$nbDiv){
                    $this->Line($graphX, $graphY+$i*$vertDivH, $graphX+$graphW, $graphY+$i*$vertDivH);
                } else{
                    $this->Line($graphX, $graphY+$graphH, $graphX+$graphW, $graphY+$graphH);
                }
            }
        }
        //draw vertical lines
        $horiDivW = floor($graphW/(count($data[$keys[0]])-1));
        if(strstr($options, 'V')){
            for($i=0;$i<=(count($data[$keys[0]])-1);$i++){
                if($i<(count($data[$keys[0]])-1)){
                    $this->Line($graphX+$i*$horiDivW, $graphY, $graphX+$i*$horiDivW, $graphY+$graphH);
                } else {
                    $this->Line($graphX+$graphW, $graphY, $graphX+$graphW, $graphY+$graphH);
                }
            }
        }
        //draw graph lines
        foreach($data as $key => $value){
            $this->setDrawColor($colors[$key][0], $colors[$key][1], $colors[$key][2]);
            $this->SetLineWidth(0.8);
            $valueKeys = array_keys($value);
            for($i=0;$i<count($value);$i++){
                if($i==count($value)-2){
                    $this->Line(
                        $graphX+($i*$horiDivW), 
                        $graphY+$graphH-($value[$valueKeys[$i]]/$maxVal*$graphH), 
                        $graphX+$graphW, 
                        $graphY+$graphH-($value[$valueKeys[$i+1]]/$maxVal*$graphH)
                    );
                } else if($i<(count($value)-1)) {
                    $this->Line(
                        $graphX+($i*$horiDivW), 
                        $graphY+$graphH-($value[$valueKeys[$i]]/$maxVal*$graphH), 
                        $graphX+($i+1)*$horiDivW, 
                        $graphY+$graphH-($value[$valueKeys[$i+1]]/$maxVal*$graphH)
                    );
                }
            }
            //Set the Key (legend)
            $this->SetFont('Courier', '', 10);
            if(!isset($n))$n=0;
            $this->Line($keyX+1, $keyY+$lineh/2+$n*$lineh, $keyX+8, $keyY+$lineh/2+$n*$lineh);
            $this->SetXY($keyX+8, $keyY+$n*$lineh);
            $this->Cell($keyW, $lineh, $key, 0, 1, 'L');
            $n++;
        }
        //print the abscissa values
        foreach($valueKeys as $key => $value){
            if($key==0){
                $this->SetXY($graphValX, $graphValY);
                $this->Cell(30, $lineh, $value, 0, 0, 'L');
            } else if($key==count($valueKeys)-1){
                $this->SetXY($graphValX+$graphValW-30, $graphValY);
                $this->Cell(30, $lineh, $value, 0, 0, 'R');
            } else {
                $this->SetXY($graphValX+$key*$horiDivW-15, $graphValY);
                $this->Cell(30, $lineh, $value, 0, 0, 'C');
            }
        }
        //print the ordinate values
        for($i=0;$i<=$nbDiv;$i++){
            $this->SetXY($graphValX-10, $graphY+($nbDiv-$i)*$vertDivH-3);
            $this->Cell(8, 6, sprintf('%.1f', $maxVal/$nbDiv*$i), 0, 0, 'R');
        }
        $this->SetDrawColor(0, 0, 0);
        $this->SetLineWidth(0.2);
    }
}
?>

Example

This example displays the same chart in 4 different ways:
<?php
require('linegraph.php');

$pdf = new PDF_LineGraph();
$pdf->SetFont('Arial', '', 10);
$data = array(
    'Group 1' => array(
        '08-02' => 2.7, 
        '08-23' => 3.0, 
        '09-13' => 3.3928571, 
        '10-04' => 3.2903226, 
        '10-25' => 3.1
    ), 
    'Group 2' => array(
        '08-02' => 2.5, 
        '08-23' => 2.0, 
        '09-13' => 3.1785714, 
        '10-04' => 2.9677419, 
        '10-25' => 3.33333
    )
);
$colors = array(
    'Group 1' => array(114, 171, 237), 
    'Group 2' => array(163, 36, 153)
);

$pdf->AddPage();
// Display options: all (horizontal and vertical lines, 4 bounding boxes)
// Colors: fixed
// Max ordinate: 6
// Number of divisions: 3
$pdf->LineGraph(190, 100, $data, 'VHkBvBgBdB', $colors, 6, 3);

$pdf->AddPage();
// Display options: horizontal lines, bounding box around the abscissa values
// Colors: random
// Max ordinate: auto
// Number of divisions: default
$pdf->LineGraph(190, 100, $data, 'HvB');

$pdf->AddPage();
// Display options: vertical lines, bounding box around the legend
// Colors: random
// Max ordinate: auto
// Number of divisions: default
$pdf->LineGraph(190, 100, $data, 'VkB');

$pdf->AddPage();
// Display options: horizontal lines, bounding boxes around the plotting area and the entire area
// Colors: random
// Max ordinate: 20
// Number of divisions: 10
$pdf->LineGraph(190, 100, $data, 'HgBdB', null, 20, 10);

$pdf->Output();
?>
View the result here.

Download

ZIP | TGZ