Creating Scalable Vector Graphs with PHP

Scaling Up

Like most PHP developers, I know a little bit about PHP’s GD extension, which makes it remarkably simple to create dynamic images in JPEG, GIF or PNG formats. This comes in particularly handy when generating complex images, such as graphs and charts, from dynamic data sets at run-time.

The downside of GD, however, is that it can only produce images in raster formats. Scaling these images up invariably reduces their quality, as the pixels get stretched to accommodate the larger size. If image scalability is a requirement, a better solution is to use a vector image format such as SVG, which represents image data as vector paths and can therefore be scaled up to a higher resolution without any distortion or quality loss.

Easier said than done. Programmatically generating graphs and charts using SVG requires a deep understanding of the SVG specification and the various SVG primitives, as well as a fair amount of time for research, experimentation and debugging. Or, in other words, that’s your entire weekend shot!

Fortunately, help is at hand. There are a number of open-source PHP libraries that support SVG chart generation, and using them can significantly reduce the amount of work involved in adding this feature to a Web application. Further, because SVG images are expressed in XML, they are easier to edit and often take up less bytes than their raster counterparts. Over the next few pages, I’ll introduce you to two such libraries, illustrating their important features and showing you just how easy it is to get your weekend back.

Putting The Pieces Together

Before diving into the code, a few notes and assumptions. I’ll assume throughout this article that you’re familiar with HTML, SQL and XML, and that you have a working Apache/PHP development environment and a Web browser with native SVG support. I’ll also assume that you know the basics of working with classes and objects in PHP, as all the components used in this article are written in compliance with OOP principles.

This article discusses two SVG charting packages, as described below:

  • eZ Components is a popular PHP component library that includes pre-rolled components for many common tasks. One of these components is the ezcGraph component, which presents a fully object-oriented API for chart generation. The component currently supports line, bar, pie, radar and odometer charts, and can output results in both vector and raster formats. The eZ Components library is freely available under the New BSD license, and is sponsored by eZ systems.
  • SVGGraph is a low-footprint PHP 4.x/5.x library for SVG graph generation. It currently only supports line, bar and pie charts, but allows extensive customization of chart appearance and colors. It produces charts compliant with SVG 1.1, and generated SVG output is consistent in all major browsers. It is freely available under the LGPL and is currently actively maintained by Graham Breach.

For both the above libraries, installation is typically as simple as uncompressing the distribution archive and adding the location of the resulting directory to the PHP include path. Detailed installation instructions can be obtained from each project’s online manual.

When It Rains…

Once you’ve got all the necessary pieces installed, it’s time to go charting! Here’s a basic example, which uses ezcGraph to generate a bar chart:

This script begins by creating a new instance of the ezcGraphBarChart class and passing it an ezcGraphArrayDataSet object containing the data set to be rendered. This data set is specified as an associative array, with keys representing X-axis labels and values representing Y-axis points. Once this data set has been attached to the chart object, the object’s renderToOutput() method takes care of generating the necessary SVG declarations to render a bar chart with the specified height and width. The renderToOutput() method will also take care of sending the correct Content-Type header to the requesting client.

Here’s what the output looks like:

Check the source code of the generated chart and you should see the SVG code that was used to generate it:

ezcGraph supports 5 different chart formats, so it’s pretty easy to represent the same data as, say, a line graph, simply by switching to a different base object:

Here’s the output:

Prefer a pie chart? No problem:

Here’s what it looks like:

Radar Sweep

Here’s a complete list of the different chart types supported by ezcGraph:

Object Chart type
ezcGraphBarChart Bar graph
ezcGraphLineChart Line graph
ezcGraphPieChart Pie chart
ezcGraphRadarChart Radar plot
ezcGraphOdometerChart Odometer chart

You’ve already seen the first three in action on the previous page, so let’s take a quick look at the remaining. A radar chart is good for multivariate data presentation, where a data set is composed of multiple different variables with a common base. Here’s an example, which demonstrates sales of different electronic appliances across different years:

Here’s what the output looks like:

Notice that each variable is represented on a different axis.

An alternative chart type is the so-called “odometer” chart, which is typically used to display the position of a single data item relative to a fixed band. Here’s an example:

Here’s what the output looks like:

To compare one data set with another, simply add additional data sets to the chart object (this only applies to line, bar and radar charts). When you do this, ezcGraph will automatically create a new plot for you, making comparative analysis easy. To illustrate, here’s an example of two data sets in a “stacked” bar graph:

Here’s what it looks like:

Notice that ezcGraph will automatically use keys from the data set array to build a legend for the chart. You can additionally include X- and Y- axis labels, as well as a title for the chart, by adjusting the chart object’s ‘xAxis’, ‘yAxis’, ‘title’ and ‘legend’ properties. Here’s a revision of the previous listing that demonstrates:

Here’s the revised output:

Mixing A Palette

The ezcGraph component allows extensive customization of output graphs, including the ability to set element colors, sizes, spacing and positioning. The simplest way to do this is through the use of “palettes”, which are essentially pre-defined color sets that can be attached to a graph. ezcGraph includes a number of pre-defined palettes, and it’s also possible to define a custom palette and use that instead.

Here’s an example of the pre-defined “green” palette:

Here’s what the output looks like:

It’s also possible to customize the font, color, borders and margins of each chart element, by accessing the corresponding element property. Here’s an example, which illustrates some of the most common element properties:

Here’s what the output looks like:

Finally, ezcGraph also allows you to place a JPEG, GIF or PNG image as the background for your chart. This can be positioned at a specific place, or repeated either horizontally or vertically across the chart. Here’s an example:

Here’s the output:

There are many more ezcGraph properties that you can play with; however, a complete description is not possible in the limited space available in this article. Take a look at the ezcGraph documentation for more information and examples.

So Many Choices

An alternative to ezcGraph is SVGGraph, a low-footprint, standalone PHP 4.x/5.x SVG charting library. Here’s a simple example, which generates a bar chart for annual rainfall data using SVGGraph:

This script begins by creating a new instance of the SVGGraph class and passing the constructor the required height and width of the output image. Next, the instance’s Values() method is used to set up the data for the chart; this method accepts an associative array, where array keys represent X-axis labels and array values represent the corresponding data points.

Once all these preliminaries have been taken care of, the instance’s Render() method takes care of actually performing all relevant calculations and producing the SVG image. The Render() method accepts one mandatory parameter, which is the type of chart required. It also accepts two optional parameters, which respectively control whether the XML document prolog and Content-Type header are included in the output.

Here’s what the output looks like:

It’s pretty easy to represent the same data as, say, a line graph, by merely changing the value passed to the Render() method:

And here’s what the revised output looks like:

Prefer a pie chart? No problem:

And here’s the output:

Notice that in all these cases, changing the chart type was as simple as passing the Render() method a different argument; the main body of the script remained unchanged. If, on the other hand, you were creating the chart “by hand” using either the DOM or SimpleXML extensions, it would be a lot of work to switch from one chart type to another. Using SVGGraph thus offers significant efficiency benefits for dynamic chart generation.

Off The Grid

While SVGGraph’s default output is acceptable for most situations, it also allows extensive customizations of chart appearance. These options are specified in an associative array, and passed to the SVGGraph object constructor as a third, optional argument.

To illustrate, consider that SVGGraph allows you to alter the colors of the chart background, grid lines, axes, labels and data point markers with the ‘back_colour’, ‘back_stroke_colour’, ‘stroke_colour’, ‘axis_colour’, ‘grid_colour’ and ‘label_colour’ options. Colours can be specified either as named strings or as RGB values. Here’s an example:

Here’s what the output looks like:

It’s also possible to adjust the visibility of elements like the chart axes, markers and background grid, with the ‘show_grid’, ‘show_axes’, ‘show_divisions’, ‘show_label_h’ and ‘show_label_v’ options. Here’s an example:

Here’s what the output looks like:

For line graphs, the ‘marker_size’, ‘marker_type’ and ‘marker_colour’ options can be used to adjust the appearance of the point markers, as shown below:

Here’s what the output looks like:

Pie charts are extremely popular, and SVGGraph comes with various properties and methods specifically for these types of charts. You’ve already seen the basic pie chart on the previous page; to enhance it, you can have SVGGraph automatically calculate and display the percentage each slice occupies of the total with the ‘show_label_percent’ option. Here’s an example:

Here’s what the output looks like:

Finally, it’s also possible to attach hyperlinks to chart labels with the Links() method, as shown below:

All Stacked Up

Now that you’ve seen what these two libraries can do, let’s wrap this up with a couple of practical examples. Assume for a moment that you have a reasonably popular Web site with lots of interesting content, and that you’ve got a PHP widget that’s diligently logging page hits and comments to a MySQL database. Assume further that the database table to which these hits are being logged looks like this:

It’s quite easy to turn this data into a stacked bar chart that displays the total number of hits versus comments per day, using the ezcGraph component. Here’s how:

Nothing too complex here – the script connects to the MySQL database, executes a SELECT query that returns the log data for the first five days of the month, and turns the result into two arrays. These arrays are then passed to the ezcGraph object’s ‘data’ property, and used to generate a stacked bar graph.

Here’s a sample of the output:

Pie, Anyone?

Another interesting application is the ability to combine AJAX with SVG to create graphs that dynamically change in response to user input. To illustrate, consider the following HTML page, which displays a form for user input and creates an SVG pie chart from that input. An AJAX call is performed with jQuery to retrieve the revised chart from the server every time the user submits new input. The retrieved SVG code is then added inline to the <object> element.

The server-side PHP script receives the GET input and turns it into a data set for use with SVGGraph’s Values() method. It then initializes an SVGGraph instance, passes it the data set, and renders a pie chart. This chart is then sent back to the client. Here’s the code:

Here’s an example of the output:

As these examples illustrate, the ezcGraph and SVGGraph libraries make it fairly easy to generate production-quality SVG graphs with very little time and effort. These graphs are typically smaller in size than their corresponding raster counterparts, with the added advantage of permitting scaling without any loss in fidelity. Try out these libraries the next time you have to generate a bar graph or pie chart, and see for yourself!

Copyright Melonfire, 2010. All rights reserved. Published on devzone.zend.com with permission.