Creating Scalable Vector Graphs with PHP

Original author: Vikram Vaswani
  • Transfer
Like most PHP developers, I am familiar with the GD extension, which makes it easy enough to create images in the formats JPEG, GIF and PNG. The extension is very convenient when you need to make complex images from dynamically obtained data on-line.
The reverse medal of GD is that images are created in raster format. Resizing an image degrades its quality.

If you need to use image resizing, the best solution would be to use a vector format such as SVG, which easily allows you to resize the image without any distortion and loss of quality.
Saying is easier than doing. Programming graphs and diagrams using SVG requires a serious understanding of the SVG specification and various SVG primitives, as well as a fair amount of time for research, experimentation, and debugging. Or, in other words, this is work for the whole weekend.
Fortunately, things are not so bad. There are a large number of open source solutions that support the creation of graphs in the SVG format, the use of which can significantly reduce the time spent on developing Web applications. In addition, the SVG format is XML, which is easy to edit and which takes up less space than their raster friends. Next, we will consider two libraries that will greatly facilitate your life.

Putting The Pieces Together

This article discusses two libraries for creating SVG images:
  • ez Components is a popular library of php components that includes most components for everyday tasks. One of these components is ezcGraph, which represents an object-oriented charting API. The component supports lines, bars, pie charts, radar and odometer charts and can display results in both formats, both in raster and in vector. The eZ Components library is distributed under the New BSD license and is sponsored by eZ systems.
  • SVGGraph PHP library for creating SVG. It supports the creation of only lines, bars, and pie charts, but allows advanced customization of appearance and colors. It allows you to create images compatible with SVG 1.1, and supports output to most modern browsers. The library is licensed under the LGPL and is actively maintained by Graham Breach.

Installation of these libraries is quite simple, you need to unpack the distributions and add the library to the include_path setting of the php.ini file. Detailed installation instructions can be found in the help on the project website.

When It Rains ...
So, after everything is complete, we will start drawing! Below is a simple example that ezcGraph uses to generate a bar chart:
  1. // set up autoloader
  2. require_once 'ezc/Base/src/ezc_bootstrap.php';
  3.  
  4. // initialize object
  5. $graph = new ezcGraphBarChart();
  6.  
  7. // add data points
  8. $graph->data['Annual rainfall'] = new ezcGraphArrayDataSet(
  9.  array(
  10.  '2002' => 18234,
  11.  '2003' => 16484,
  12.  '2004' => 16574,
  13.  '2005' => 17464,
  14.  '2006' => 19474
  15. ));
  16.  
  17.  
  18. // render graph
  19. $graph->renderToOutput(500,500);
  20. ?>
* This source code was highlighted with Source Code Highlighter.

This script creates an object of the ezcGraphBarChart class in which an object of the ezcGraphArrayDataSet class is created containing the data to be drawn. The data is presented in the form of an associative array, the keys of which are values ​​located on the X axis, and the values ​​are values ​​on the Y axis. After the data has been attached to the chart object, renderToOutput () takes care of plotting the chart in the specified width and height parameters , the correct specification of the Content-Type headers.
Something similar to this

will be generated : Look at the source code of the generated chart and you will see the SVG code that is used to display this image:

ezcGraph supports 5 different chart formats, it is easy to illustrate how the chart will look in a different format, simply replacing the class of the object:
  1. // set up autoloader
  2. require_once 'ezc/Base/src/ezc_bootstrap.php';
  3.  
  4. // initialize object
  5. $graph = new ezcGraphLineChart();
  6.  
  7. // add data points
  8. $graph->data['Annual rainfall'] = new ezcGraphArrayDataSet(
  9.  array(
  10.  '2002' => 18234,
  11.  '2003' => 16484,
  12.  '2004' => 16574,
  13.  '2005' => 17464,
  14.  '2006' => 19474
  15. ));
  16.  
  17. // render graph
  18. $graph->renderToOutput(500,500);
  19. ?>
* This source code was highlighted with Source Code Highlighter.

Here's what it will look like:

Need a pie chart - no problem:
  1. // set up autoloader
  2. require_once 'ezc/Base/src/ezc_bootstrap.php';
  3.  
  4. // initialize object
  5. $graph = new ezcGraphPieChart();
  6.  
  7. // add data points
  8. $graph->data['Annual rainfall'] = new ezcGraphArrayDataSet(
  9.  array(
  10.  '2002' => 18234,
  11.  '2003' => 16484,
  12.  '2004' => 16574,
  13.  '2005' => 17464,
  14.  '2006' => 19474
  15. ));
  16.  
  17. // render graph
  18. $graph->renderToOutput(500,500);
  19. ?>
  20.  
* This source code was highlighted with Source Code Highlighter.

Here's what it will look like:


Radar Sweep
Below is a detailed list of the various chart types supported by ezcGraph:
ObjectChart type
ezcGraphBarChartBar graph
ezcGraphLineChartLine graph
ezcGraphPieChartPie chart
ezcGraphRadarChartRadar plot
ezcGraphOdometerChartOdometer chart


You have already seen how the first three classes work, so let's look at the rest. A radar chart is good for illustrating multidimensional data. Below is an example that demonstrates the sales of various electronic products over several years:
  1. // set up autoloader
  2. require_once 'ezc/Base/src/ezc_bootstrap.php';
  3.  
  4. // initialize object
  5. $graph = new ezcGraphRadarChart();
  6.  
  7. // add data sets
  8. $graph->data['Televisions'] = new ezcGraphArrayDataSet(
  9.  array(
  10.  '2002' => 1823,
  11.  '2003' => 1644,
  12.  '2004' => 1574,
  13.  '2005' => 1764,
  14.  '2006' => 1944,
  15.  '2007' => 1201,
  16.  ''   => 1823
  17. ));
  18. $graph->data['Audio systems'] = new ezcGraphArrayDataSet(
  19.  array(
  20.  '2002' => 758,
  21.  '2003' => 144,
  22.  '2004' => 154,
  23.  '2005' => 714,
  24.  '2006' => 638,
  25.  '2007' => 1038, 
  26.  ''   => 758
  27. ));
  28. $graph->data['Cameras'] = new ezcGraphArrayDataSet(
  29.  array(
  30.  '2002' => 102,
  31.  '2003' => 143,
  32.  '2004' => 176,
  33.  '2005' => 270,
  34.  '2006' => 212,
  35.  '2007' => 1112,
  36.  ''   => 102
  37. ));
  38.  
  39. // render graph
  40. $graph->renderToOutput(500,500);
  41. ?>
  42.  
* This source code was highlighted with Source Code Highlighter.

Here's what it will look like:

Note that each variable is located on its own axis.
Another type of graph - an odometer - is used to illustrate some value relative to a fixed range. Below is an example:
  1. // set up autoloader
  2. require_once 'ezc/Base/src/ezc_bootstrap.php';
  3.  
  4. // initialize object
  5. $graph = new ezcGraphOdometerChart();
  6.  
  7. // add data point
  8. $graph->data['Televisions'] = new ezcGraphArrayDataSet(
  9.  array(2400)
  10. );
  11.  
  12. // set odometer limits
  13. $graph->axis->min = 0;
  14. $graph->axis->max = 3000;
  15.  
  16. // render graph
  17. $graph->renderToOutput(500,500);
  18. ?>
* This source code was highlighted with Source Code Highlighter.

Here's what it will look like:


To compare one dataset with another, simply add an extra dataset to the chart object (this works for lines, bars, and radar charts). When you do this, ezcGraph will automatically create a new chart, making data comparison simple enough. To illustrate, see an example:
  1. // set up autoloader
  2. require_once 'ezc/Base/src/ezc_bootstrap.php';
  3.  
  4. // initialize object
  5. $graph = new ezcGraphBarChart();
  6.  
  7. // add data points
  8. $graph->data['Annual rainfall'] = new ezcGraphArrayDataSet(
  9.  array(
  10.  '2002' => 18234,
  11.  '2003' => 16484,
  12.  '2004' => 16574,
  13.  '2005' => 17464,
  14.  '2006' => 19474
  15. ));
  16. $graph->data['Crop production'] = new ezcGraphArrayDataSet(
  17.  array(
  18.  '2002' => 50474,
  19.  '2003' => 26749,
  20.  '2004' => 29567,
  21.  '2005' => 37869,
  22.  '2006' => 79400
  23. ));
  24.  
  25. // render graph
  26. $graph->renderToOutput(500,500);
  27. ?>
* This source code was highlighted with Source Code Highlighter.

Here's what it will look like:

Note that ezcGraph will automatically use the keys to the dataset as the legend of the graph. You can optionally include the labels of the X and Y axes, as well as the title of the chart using the properties 'xAxis', 'yAxis', 'title' and 'legend'. Below is the modified code:
  1. // set up autoloader
  2. require_once 'ezc/Base/src/ezc_bootstrap.php';
  3.  
  4. // initialize object
  5. $graph = new ezcGraphBarChart();
  6.  
  7. // add data points
  8. $graph->data['Annual rainfall'] = new ezcGraphArrayDataSet(
  9.  array(
  10.  '2002' => 18234,
  11.  '2003' => 16484,
  12.  '2004' => 16574,
  13.  '2005' => 17464,
  14.  '2006' => 19474
  15. ));
  16.  
  17. // set title
  18. $graph->title = 'ANNUAL RAINFALL';
  19. // set axis labels
  20. $graph->xAxis->label = 'YEAR';
  21. $graph->yAxis->label = 'MM';
  22.  
  23. // set legend and title position
  24. $graph->title->position = ezcGraph::TOP;
  25. $graph->legend->position = ezcGraph::RIGHT;
  26. // render graph
  27. $graph->renderToOutput(500,500);
  28. ?>
* This source code was highlighted with Source Code Highlighter.

Here's what it will look like:


Mixing A Palette
ezcGraph allows you to make advanced graph settings, including the ability to set colors, sizes, gaps and positioning of elements. An easy way to do this is to use the “palettes” property, which can contain predefined colors. ezcGraph includes a number of predefined palettes, while at the same time you can create your own palette.
Below is an example of a predefined green palette:
  1. // set up autoloader
  2. require_once 'ezc/Base/src/ezc_bootstrap.php';
  3.  
  4. // initialize object
  5. $graph = new ezcGraphBarChart();
  6.  
  7. // use green palette
  8. $graph->palette = new ezcGraphPaletteEzGreen();
  9.  
  10. // add data points
  11. $graph->data['Annual rainfall'] = new ezcGraphArrayDataSet(
  12.  array(
  13.  '2002' => 18234,
  14.  '2003' => 16484,
  15.  '2004' => 16574,
  16.  '2005' => 17464,
  17.  '2006' => 19474
  18. ));
  19.  
  20.  
  21. // render graph
  22. $graph->renderToOutput(500,500);
  23. ?>
* This source code was highlighted with Source Code Highlighter.

Here's what it looks like:

It is also possible to change the font, color, borders, alignment for each element of the graph, gaining access to the properties of a particular element. Below is an example:
  1. // set up autoloader
  2. require_once 'ezc/Base/src/ezc_bootstrap.php';
  3.  
  4. // initialize object
  5. $graph = new ezcGraphBarChart();
  6.  
  7. // add data points
  8. $graph->data['Annual rainfall'] = new ezcGraphArrayDataSet(
  9.  array(
  10.  '2002' => 18234,
  11.  '2003' => 16484,
  12.  '2004' => 16574,
  13.  '2005' => 17464,
  14.  '2006' => 19474
  15. ));
  16.  
  17. // set title
  18. $graph->title = 'ANNUAL RAINFALL';
  19. // set axis labels
  20. $graph->xAxis->label = 'YEAR';
  21. $graph->yAxis->label = 'MM';
  22.  
  23. // set global options for font name and size
  24. $graph->options->font->name = 'Arial';
  25. $graph->options->font->maxFontSize = '40';
  26.  
  27. // set legend and title font
  28. $graph->legend->font->name = 'Times New Roman';
  29. $graph->title->font->name = 'Arial';
  30. $graph->title->font->maxFontSize = '20';
  31.  
  32. // set legend and title colors
  33. $graph->title->font->color = '#FFFF00';
  34. $graph->legend->font->color = '#FFFFFF';
  35.  
  36. // set bar color
  37. $graph->data['Annual rainfall']->color = '#FF8040';
  38.  
  39. // set legend and title borders and border colors
  40. $graph->legend->border = '#FF8040';
  41. $graph->title->borderWidth = '2';
  42. $graph->title->border = '#FF00FF';
  43. $graph->title->background = '#C0C0C0';
  44.  
  45. // set colors for X and Y axes
  46. $graph->xAxis->border = '#FF0000';
  47. $graph->yAxis->border = '#00FF00';
  48.  
  49. // set legend and title position
  50. $graph->title->position = ezcGraph::TOP;
  51. $graph->legend->position = ezcGraph::RIGHT;
  52. // render graph
  53. $graph->renderToOutput(500,500);
  54. ?>
* This source code was highlighted with Source Code Highlighter.

Here's what it looks like:

ezcGraph allows you to place JPEG, GIF, or PNG images as the background for your graphic. The image can be placed in a specific place or repeated both horizontally and vertically. Below is an example:
  1. // set up autoloader
  2. require_once 'ezc/Base/src/ezc_bootstrap.php';
  3.  
  4. // initialize object
  5. $graph = new ezcGraphBarChart();
  6.  
  7. // add data points
  8. $graph->data['Annual rainfall'] = new ezcGraphArrayDataSet(
  9.  array(
  10.  '2002' => 18234,
  11.  '2003' => 16484,
  12.  '2004' => 16574,
  13.  '2005' => 17464,
  14.  '2006' => 19474
  15. ));
  16.  
  17. // set title
  18. $graph->title = 'ANNUAL RAINFALL';
  19. // set axis labels
  20. $graph->xAxis->label = 'YEAR';
  21. $graph->yAxis->label = 'MM';
  22.  
  23. // repeat background image horizontally across graph bottom
  24. $graph->background->image = 'logo.jpg';
  25. $graph->background->position = ezcGraph::BOTTOM;
  26. $graph->background->repeat = ezcGraph::HORIZONTAL;
  27. // render graph
  28. $graph->renderToOutput(500,500);
  29. ?>
* This source code was highlighted with Source Code Highlighter.

Here's what it will look like:

There are still quite a number of features that ezcGraph presents. See the ezcGraph documentation

So Many Choices
for more. An alternative to ezcGraph is SVGGraph. Below is a simple example that creates a bar graph for annual rainfall:
  1. // include class file
  2. include 'SVGGRaph/SVGGraph.php';
  3.  
  4. // initialize object
  5. $graph = new SVGGraph(400, 400);
  6.  
  7. // add data points
  8. $graph->Values(array(
  9.  '2002' => 18234,
  10.  '2003' => 16484,
  11.  '2004' => 16574,
  12.  '2005' => 17464,
  13.  '2006' => 19474
  14. ));
  15.  
  16. // render graph
  17. $graph->Render('BarGraph');
  18. ?>
* This source code was highlighted with Source Code Highlighter.

This script begins by creating an SVGGraph object and passing the required width and height dimensions to the constructor. Next, the Values ​​() method is used to pass data information; This method takes an associative array as a parameter, in which the keys are the coordinates along the X axis, and the array values ​​correspond to the values ​​along the Y axis.
After these actions, Render () takes care of all the necessary calculations and creating the SVG image. The Render () method requires one required parameter, which is the type of the plotted plot. It also has two optional parameters that are responsible for outputting the beginning of the XML document and the need to display the Content-Type header.
Here's how it would look:

It is very easy to see the same data, but only in a different format, say lines. It is only necessary to change the parameter of the Render () method:
  1. // include class file
  2. include 'SVGGRaph/SVGGraph.php';
  3.  
  4. // initialize object
  5. $graph = new SVGGraph(400, 400);
  6.  
  7. // add data points
  8. $graph->Values(array(
  9.  '2002' => 18234,
  10.  '2003' => 16484,
  11.  '2004' => 16574,
  12.  '2005' => 17464,
  13.  '2006' => 19474
  14. ));
  15.  
  16. // render graph
  17. $graph->Render('LineGraph');
  18. ?>
  19.  
* This source code was highlighted with Source Code Highlighter.

Here's how it will look.

Need a pie chart - no problem.
// include class file
include 'SVGGRaph/SVGGraph.php';

// initialize object
$graph = new SVGGraph(400, 400);

// add data points
$graph->Values(array(
 'UK' => 50,
 'US' => 30,
 'Europe' => 100,
 'India' => 20,
));

// render graph
$graph->Render('PieGraph');
?>

* This source code was highlighted with Source Code Highlighter.

Here's what it will look like.


Note that in all these cases, changing the type of the chart was simple, just passing another argument to Render () while the main part of the script remained unchanged. If you were to create a chart “manually” using either the DOM or SimpleXML, it would take a lot of work to move from one type of chart to another.

Off The Grid
Although the default output SVGGraph is applicable to almost any situation, the library offers quite a lot of opportunities for customizing the appearance of the diagrams. Settings are passed as an associative array and passed to the constructor of the SVGGraph object as the third optional element.
For example, SVGGraph allows you to change the background color of a chart, grid line, axes, headers, point markers using the settings 'back_colour', 'back_stroke_colour', 'stroke_colour', 'axis_colour', 'grid_colour' and 'label_colour'. Color can be specified both as a string and as an RGB value. Below is an example:
// include class file
include 'SVGGRaph/SVGGraph.php';

// set options
$options = array(
 'back_colour' => 'white',
 'back_stroke_colour' => 'pink',
 'stroke_colour' => 'black',
 'axis_colour' => 'blue',
 'grid_colour' => 'silver',
 'label_colour' => 'brown'
);

// initialize object
$graph = new SVGGraph(400, 400, $options);

// add data points
$graph->Values(array(
 '2002' => 18234,
 '2003' => 16484,
 '2004' => 16574,
 '2005' => 17464,
 '2006' => 19474
));

// render graph
$graph->Render('BarGraph');
?>

* This source code was highlighted with Source Code Highlighter.

Here's what it will look like:

There is also the ability to control the visibility of elements such as axes, markers, the background grid using the options 'show_grid', 'show_axes', 'show_divisions', 'show_label_h' and 'show_label_v'. Below is an example:
// include class file
include 'SVGGRaph/SVGGraph.php';

// set options
$options = array(
 'show_grid' => false,
 'show_axes' => true,
 'show_divisions' => false,
 'show_label_h' => true,
 'show_label_v' => false
);

// initialize object
$graph = new SVGGraph(400, 400, $options);

// add data points
$graph->Values(array(
 '2002' => 18234,
 '2003' => 16484,
 '2004' => 16574,
 '2005' => 17464,
 '2006' => 19474
));

// render graph
$graph->Render('BarGraph');
?>

* This source code was highlighted with Source Code Highlighter.

Here's what it will look like:

For a line chart, the parameters 'marker_size', 'marker_type' and 'marker_colour' can be used to control the appearance of point markers, as shown below:
// include class file
include 'SVGGRaph/SVGGraph.php';

// set options
$options = array(
 'show_grid' => false,
 'marker_size' => 8,
 'marker_type' => 'triangle',
 'marker_colour' => 'red'
);

// initialize object
$graph = new SVGGraph(400, 400, $options);

// add data points
$graph->Values(array(
 '2002' => 18234,
 '2003' => 16484,
 '2004' => 16574,
 '2005' => 17464,
 '2006' => 19474
));

// render graph
$graph->Render('LineGraph');
?>

* This source code was highlighted with Source Code Highlighter.

Here's what it will look like:

Pie charts are very popular and SVGGraph has a large number of settings and methods specific to this type of chart. The example of using pie charts was higher, let's expand it, for which we make SVGGraph automatically calculate and display percentages using 'show_label_percent'. Below is an example:
// include class file
include 'SVGGRaph/SVGGraph.php';

// initialize object
$graph = new SVGGraph(400, 400, array(
 'show_label_amount'  => true,
 'show_label_percent' => true,
 'label_colour'    => 'black',
));

// add data points
$graph->Values(array(
 'UK'   => 50,
 'US'   => 30,
 'Europe' => 100,
 'India'  => 20,
));

// render graph
$graph->Render('PieGraph');
?>

* This source code was highlighted with Source Code Highlighter.

Here's what it will look like:

Finally, it is possible to add a hyperlink to the labels on the chart using the Links () method as shown below:
// include class file
include 'SVGGRaph/SVGGraph.php';

// initialize object
$graph = new SVGGraph(400, 400, array(
 'show_label_amount'  => true,
 'show_label_percent' => true,
 'label_colour'    => 'black',
));

// add data points
$graph->Values(array(
 'UK'   => 50,
 'US'   => 30,
 'Europe' => 100,
 'India'  => 20,
));

// add links
// no link for 'Europe' slice
$graph->links(array(
 'UK'   => 'http://example.org/UK',
 'US'   => 'http://example.org/US',
 'India'  => 'http://example.org/IN',
));

// render graph
$graph->Render('PieGraph');
?>

* This source code was highlighted with Source Code Highlighter.


All Stacked Up
So we looked at the possibilities of two popular libraries, let's see some practical examples. Suppose you are the owner of a popular site with a lot of interesting content, and you have a PHP script that records the number of visits and comments on a page in a MySQL database. Suppose the database is as follows:
+----+------------+------+-------+
| id | date    | hits | posts |
+----+------------+------+-------+
| 1 | 2010-02-01 | 3849 |  284 |
| 2 | 2010-02-02 | 3728 |  421 |
| 3 | 2010-02-03 | 3526 |  189 |
| 4 | 2010-02-04 | 4288 |  143 |
| 5 | 2010-02-05 | 4526 |  265 |
...
+----+------------+------+-------+

* This source code was highlighted with Source Code Highlighter.

There is nothing easier than translating the contents of this table into a graph showing the number of visits along with the number of comments using ezcGraph. Example below:
// set up autoloader
require_once 'ezc/Base/src/ezc_bootstrap.php';

// query database for data
// formulate into arrays
try {
 $pdo = new PDO('mysql:host=localhost;dbname=example', 'user', 'pass');
 $sql = "SELECT DATE_FORMAT(date, '%d') AS day, hits, posts FROM log WHERE date BETWEEN '2010-02-01' AND '2010-02-05'";
 if ($result = $pdo->query($sql)) {
  while($row = $result->fetch()) {
   $hits[$row['day']] = $row['hits'];
   $posts[$row['day']] = $row['posts'];
  }
 } 
} catch (PDOException $e) {
 die('Error: ' . $e->getMessage());
}
  
// initialize object
$graph = new ezcGraphBarChart();

// add data sets
$graph->data['Hits'] = new ezcGraphArrayDataSet($hits);
$graph->data['Posts'] = new ezcGraphArrayDataSet($posts);

// render graph
$graph->renderToOutput(500,500);
?>


* This source code was highlighted with Source Code Highlighter.

There is nothing complicated, the script connects to MySQL, performs SELECT, which returns data for 5 days and adds the data into two arrays. These arrays are passed to the 'data' property of the ezcGraph object.
Here's what it looks like:


Pie, Anyone?
Another interesting opportunity is to connect AJAX with SVG to create a dynamically changing chart depending on user input. Consider an HTML page that displays a form and creates a pie chart, depending on the data entered. AJAX requests are made using jQuery every time a user modifies data. We will embed the received answer directly inside

Also popular now: