Version | Date | Status | Who | Comment |
---|---|---|---|---|
R1.7 | 2004-09-12 | Released | Johan Persson | Added additional info for JpGraph 1.17-beta. Changed format. |
R1.6 | 2004-07-03 | Released | Johan Persson | Added additional info for JpGraph 1.16 |
R1.5 | 2004-05-10 | Released | Johan Persson | Added additional info for JpGraph 1.15 |
R1.4 | 2003-11-23 | Released | Johan Persson | Added additional info for JpGraph 1.14 |
R1.3 | 2003-04-06 | Released | Johan Persson | Added additional info for JpGraph 1.13 |
R1.2 | 2003-02-02 | Released | Johan Persson | Added additional info for JpGraph 1.11 |
R1.1 | 2002-12-26 | Released | Johan Persson | Added additional info for JpGraph 1.10 |
R1.0 | 2002-10-05 | Released | Johan Persson | Added additional info, proper indexing |
D1.0 | 2002-09-16 | Draft | Johan Persson | Initial version |
To generate the images automatically in the img directory a custom awk-script is used to extract all the used image script from the manual. The script then uses the client version of PHP generate the images from the scripts and stores them in the 'img' directory.
The final set of HTML files was then processes by HTMLDOC to construct table of contents and chapter links.
Even though the library is known to work with version of PHP prior to 4.3 the library is not tested nor is it recommended to run with any older versions of PHP.
Some highlights of available features are
The current version as of this writing is 1.17-beta
Note. I keep a strait-forward version scheme to avoid the version number inflation. This means
Please report bugs using the JpGraph BugTracker available at http://www.aditus.nu/bugtraq/
Please note that this library is only guaranteed to work with PHP versions >= 4.3.
You can easily verify this by making sure that your installation of PHP supports some of the 'imagecreate()' functions.
This means that you must have a working GD-library together with PHP before even thinking of running JpGraph. Please make sure you have version 4.1 or above of PHP since JpGraph is not tested with versions prior to PHP 4.1. Ideally you should use at least PHP 4.3.x
If you want to use TTF fonts you must also make sure that your PHP installation supports TTF fonts (either through FreeType 1 or FreeType 2 libraries). In additions to this you need at least a couple of TTF fonts. In preparation of using TTF fonts with JpGraph you must specify, in jpgraph.php , where those font files can be found.
JpGraph uses a naming convention for the TTF font files in order to be able to find the correct font files. You should therefore use the font files that can be downloaded together with JpGraph.
$im = @ImageCreate (150, 100)
or die ("Cannot create a new GD image.");
$background_color = ImageColorAllocate ($im, 255, 255, 255);
$text_color = ImageColorAllocate ($im, 233, 14, 91);
ImageString ($im, 1, 5, 5, "A Simple Text String", $text_color);
header ("Content-type: image/png");
ImagePng ($im);
The above script must work before you will have any chance of getting JpGraph working.
$im = imagecreatetruecolor (300, 200);
$black = imagecolorallocate ($im, 0, 0, 0);
$white = imagecolorallocate ($im, 255, 255, 255);
imagefilledrectangle($im,0,0,399,99,$white);
imagerectangle($im,20,20,250,190,$black);
header ("Content-type: image/png");
imagepng ($im);
After running this script you should now see a black rectangle in your browser.
In all cases you must have a suitable TTF font that supports the non-latin based language you want to use.
For Cyrillic support you need to set the define LANGUAGE_CYRILLIC in jpgraph.php to true. You can then use a suitable Cyrillic font as replacement for the ordinary fonts.
For Chinese JpGraph supports both BIG5 and gb2312 encoding. For BIG5 encoding your PHP installation must have support for the "iconv()" function. Furthermore you need to set the define CHINESE_TTF_FONT to the name of the Chinese BIG5 font you want to use. By default this is set to "bkai00mp.ttf". To use the Chinese BIG5 font for your texts you need to specify the font family as FF_CHINESE.
If you instead want to use the simsun.ttc of simhei.ttf fonts which use the gb2312 encoding you only need to install those fonts in the normal TTF font directory and then specify the font family as FF_SIMSUN (the simhei.ttf is used when you specify the fonts style as FS_BOLD.
Please make sure that PHP has write permissions to the cache directory if you plan to use the cache feature. If not you will get a "Can't write file xxx.yyy" error when you try to generate a graph. You can read more about how to use the cache in the chapter Making sense of caching system in JpGraph
If you want JPEG support you will also need an additional library for PHP, again please see PHP documentation for specifics. For most practical purposes PNG is a better format since it normally achieves better compression then GIF (typically by a factor of 2 for the types of images generated by JpGraph). In comparison with JPEG format PNG is also better for the type of images generated by this library. So, the bottom line is, you should have a very good reason to choose any other format then PNG.
By default the image format is set to "auto". This means that JpGraph automatically chooses the best available graphic using the preferred order "PNG", "GIF", "JPG".
Experience shows that most of the trouble are caused by either an old buggy version of the free-type TTF library or using an old antiquated version of the GD library. In order to narrow it down you could try the following steps.
The other reasons is that in some rare cases the auto detection of the GD library could get it wrong. If you in fact only have GD1 when the library mistakenly thinks you have GD2 this could in rare cases cause PHP to crash. Please try re-run the example by setting the DEFINE USE_GD2_LIBRARY to "false".
./configure --prefix=/usr/share \ --datadir=/usr/share/php \ --with-apxs=/usr/sbin/apxs \ --libdir=/usr/share \ --includedir=/usr/include \ --bindir=/usr/bin \ --with-config-file-path=/etc \ --enable-mbstring --enable-mbregex \ --with-pdflib=/usr \ --with-mysql \ --with-ttf-dir=/usr/lib \ --with-freetype-dir=/usr/lib \ --with-gd --enable-gd-imgstrttf --enable-gd-native-ttf \ --with-zlib-dir=/usr/lib \ --with-png-dir=/usr/lib --with-jpeg-dir=/usr/lib --with-xpm-dir=/usr/X11R6 \ --with-tiff-dir=/usr/lib \ --enable-ftp \ --enable-memory-limit --enable-safe-mode \ --bindir=/usr/bin \ --enable-bcmath -enable-calendar \ --enable-ctype --with-ftp \ --enable-magic-quotes \ --enable-inline-optimization \ --with-bz2 \ --with-iconv
<img src="fig1.php" border=0
align=center width=300 height=200>
The library will automatically generate the necessary headers to be sent back to the browser to correctly recognize the data stream as an image of either PNG/GIF/JPEG format. The browser can then correctly decode the image
Observe that you can't return anything else than an image from the image script. By definition each HTML page can only consist of one mime type which is determined by the sent headers.
A common mistake is to have a space in the beginning of the image script file which the HTTP server will send back to the browser. The browser now assumes that the data coming back from this script is normal ASCII. When then the image headers get send back to the browser to forewarn the browser of the forthcoming image the browser will not like that. It has already determined that the script should only send ASCII data back and will then give you a "Headers already sent error".
To include several images together with text on a page you need to have a parent page with several <IMG> which each refers to an image script.
To get access to the library you will need to include at least two
files, the base library and one or more of the plot extensions. So for
example if you want to do line plots the top of your PHP file must have
the lines:
php
include (
'jpgraph.php');
include ('jpgraph_line.php');
...
// Code that uses the jpgraph
library
...
Please make sure that you run the command line version of PHP (cli). Using the CGI SAPI version will not work since then the HTTP headers will be generated. You can easily check this by running
php --versionyou should then get a response with something like
PHP 4.3.8 (cli) (built: Aug 29 2004 22:48:10) Copyright (c) 1997-2004 The PHP Group Zend Engine v1.3.0, Copyright (c) 1998-2004 Zend TechnologiesThe important thing here is the
(cli)marker. The JpGraph library check from what SAPI API it is invoked from and adjusts the header generation accordingly.
If all the requirements above are met then images can be generated directly on the command line. For example by
$> php myimage.php > image.png
You should remember that it is also possible to pass arguments to
the image script via the normal HTTP parameters, for example
<img src="showgraph.php?a=1&b=2">
This could for example be used to control the appearance of the image or perhaps send data to the image which will be displayed. Note that this is probably not the best way to send large amount of data to plot. Instead the only practical way, for large data sizes, is to get all the data in the image script, perhaps from a DB.
echo "<img
src='myimagescript.php?dummy=".now()."'>"
When it comes to the structure of your imaging script they will
generally have the structure
// ... Include necessary headers
$graph = new Graph($width,$height, ...);
// ... code to construct the graph details
$graph->Stroke();
JpGraph is completely Object oriented so all calls will be action on specific instances of classes. One of the fundamental classes is the Graph() class which represents the entire graph.
After the creation of the Graph() object you add all your lines of code to construct the details of the graph.
As the final call you will send the generated image back to the browser with a call to the Stroke() method.
Note: This is not always true, but to keep things simple for the moment we assume this.
In addition to this standard usage pattern you can also send the
graph directly to a file, get the GD image handler for the image and
also make use of the builtin cache system. The cache system, which
lessens the burden of the PHP server, works by avoiding o run all the
code that follows the initial Graph() call by checking if the image has
already been created and in that case directly send back the previously
created (and filed) image to the browser. When using the cache system
you must specify a filename which is used to store the image in the
cache system and possibly also a timeout value to indicate how long the
image in the cache directory should be valid. For this reason you might
in the following examples, for example, see the code
$graph = new Graph(300,200,"auto");
in the start of all the examples. The two first parameters specify the width and height of the graph and the third parameter the name of the image file in the cache directory. The special name 'auto' indicates that the image file will be given the same name as the image script but with the extension changed to indicate the graphic format used, i.e '.jpg', '.png' and so on.
DEFINE("DEFAULT_GFORMAT","auto");
$graph->img->SetImgFormat("jpeg")
$graph->Stroke("/usr/home/peter/images/result2002.png");
Please note that the user running as Apache/PHP must have write access to the specified directory.
There are also two predefined filenames which have special meaning.
$handle = $graph->Stroke(_IMG_HANDLER);
In many of the example you can see examples of both TrueType and Bitmap fonts.
There are a number of subtle differences in the way builtin fonts and TrueType fonts are rendered to the screen. However, JpGraph, abstracts away 99.9% of the differences so it will be, for the user, completely transparent to switch between the different fonts.
DEFINE("TTF_DIR","/usr/local/fonts/ttf/");
Since JpGraph must be able to tell the difference between the italic and bold versions of the same font family a standard naming convention is used to name the files. The available fonts are also defined by DEFINES and hence you can't just copy your own TTF files to the directory and expect it to work. At the moment there is no "easy" way to add new fonts but to make some (small) mods to the code. However this is expected to change in future version of JpGraph.
DEFINE("TTF_DIR","/usr/X11R6/lib/X11/fonts/truetype/");
$im = imagecreatetruecolor (400, 100);
$black = imagecolorallocate ($im, 0, 0, 0);
$white = imagecolorallocate ($im, 255, 255, 255);
imagerectangle($im,0,0,399,99,$black);
imagefilledrectangle($im,0,0,399,99,$white);
imagettftext ($im, 30, 0, 10, 40, $black, TTF_DIR."arial.ttf",
"Hello World!");
header ("Content-type: image/png");
imagepng ($im);
The above script assumes you have the GD2 library and will create an image with the classical "Hello World!" text printed in black.
Font family | Type | Note |
FF_FONT0 | Builtin font | A very small font, only one style |
FF_FONT1 | Builtin font | A medium sized font |
FF_FONT2 | Builtin font | The largest bit mapped font |
FF_ARIAL | TTF font | Arial font |
FF_VERDANA | TTF font | Verdana font |
FF_COURIER | TTF font | Fix pitched courier |
FF_BOOK | TTF font | Bookman |
FF_COMIC | TTF font | Comic sans |
FF_TIMES | TTF font | Times New Roman |
FF_GEORGIA | TTF font | Georgia |
FF_TREBUCHE | TTF font | Trebuche |
FF_VERA | TTF font | Gnome Vera font, Available from http://www.gnome.org/fonts/ |
FF_VERAMONO | TTF font | Gnome Vera Mono font, Available from http://www.gnome.org/fonts/ | FF_VERASERIF | TTF font | Gnome Vera Serif font, Available from http://www.gnome.org/fonts/ |
FF_CHINESE | TTF font | Installed chinese font |
FF_SIMSUN | TTF font | Installed chinese font |
FF_BIG5 | TTF font | Installed chinese BIG5 font (needs iconv()) |
Please note that not all font families support all styles. The figure below illustrates each of the available font families and what styles you may use.
We finally show some example of valid font specifications
$graph->title->SetFont(FF_FONT2);
$graph->title->SetFont(FF_FONT2,FS_BOLD);
$graph->title->SetFont(FF_ARIAL);
$graph->title->SetFont(FF_ARIAL,FS_BOLD,24);
In order to add you favorite fonts there are three steps you need to follow :
Text is added to a graph with the creation of a Text() object. And the alignment is specified with Text::Align() Text alignment might actually be a misguiding name. What you specify is rather the anchor point for the text, i.e. when you specify that a text should be positioned at position (x,y) how is that coordinate to be interpretated.
The image below shows a text string aligned in the 9 possible combinations. In the image the red crosses indicate what coordinate that text string was positioned at. The alignment used for each of the cases is shown below.
SetColor("khaki");
A named color can also be modified by adding a adjustment factor. An
adjustment factor, 0 < f < 1, a smaller value will give a darker
version and a value of 0 or 1 will return the original color. A value >
1 will make the color brighter. A few examples
SetColor("khaki:0.5"); // A darker
version of "khaki"
SetColor("yellow:1.2"); // A slightly lighter version of "yellow"
SetColor(array(65,100,176));
SetColor("#A16BFF");
For example to specify a red color which is 40% transparent you
write
SetColor("red@0.4");
or to specify 90% transperancy you write
SetColor("red@0.9");
Below is an example of how a bar graph with a background image can make use of transperancy
Theme 2: Pastel
Theme 3: Water
Theme 4: Sand
Depending on the complexity of the image script (for example if it is doing several DB lookups) this could significantly improve performance.
The rationale behind this is of course performance, and the observation that very few graphs are really real-time, i.e. needs to be updated absolutely every time the graphing script is called.
DEFINE("USE_CACHE",true);
DEFINE("READ_CACHE",true)
The first of these, USE_CACHE, is the master-switch which must be set to true to enable the caching system. The second switch READ_CACHE very seldom needs to be changed.
This second switch basically tells whether or not JpGraph should ever look in the cache. Setting this to false and the master-switch to true would then always generate an new updated image file in the cache and this new image would be send back to the browser. The main use for this (admittedly) strange setting is if you like to have the side effect of the script that a fresh image is always stored in the cache directory.
Once you have enabled the cache you must also make sure that a valid cache directory is setup. The cache directory is specified with the define
DEFINE("CACHE_DIR","/tmp/jpgraph_cache/");
You can of course change the default directory to whatever directory you fancy. But, you must remember one important thing. The cache directory must be writable for the user running Apache/PHP .
These parameters are supplied in the initial Graph() method call which should be among the first in your script. Instead of manually specifying a file name to be used you could often use the special name "auto". If the filename is specified as "auto" the cashed image will then be named the same as the image script but with the correct extension depending on what image format have been chosen.
If you don't specify a file name no caching will be used no matter the settings of USE_CACHE (without a file name it is impossible!)
The following call to Graph() shows a typical use of the cache.
$graph = new Graph(300,200,"auto",60)
The above code will use the automatic filename and a make the cache valid for 60 minutes.
So, how does this all work now?
The first time you call your script (no cached image) everything will be as usual, the script will run and you will in the end send back the image to the browser. However if you have the caching enabled JpGraph will automatically have stored a copy of the generated image in the cache directory.
The next time you call the script the first thing that happens in the initial Graph() is that it will go and check in the cache directory if the named image exists there. If this is the case it will also checks that the image isn't too old (as compared to the specified timeout value). If the image is valid then the image will be streamed straight back from the image file to the browser and the script will end it's execution.
Hence, if the image is found in the cache no code lines after the initial Graph() call will be executed
The design decision behind this is that your image script code never has to include anything special to make full use of the cache. It will just automatically work.
The performance benefits even for simple CSIM images is around 50% if the cache can be used and can of course be several 1000% if construction of the image requires DB calls and other complex operations which can be avoided.
Before reading further you should have an understanding on how the CSIM works by reading the section "Using Client side image maps".
Please remember that when using CSIM you must end your script with a call to Graph::StrokeCSIM() method instead of the Graph::Stroke() used for non-csim.
To use the cache with CSIM you have to call the Graph::CheckCSIMCache(). As with the caching for non-CSIM you have to supply a name to be used for the cached version as well as an optional timeout value. The default timeout value if nothing else is specified is 60 minutes.
The name argument requires some more explanations. You must specify a relative name here. For example "myimage" or perhaps "firstpage/image3". Depending on your installation of JpGraph this will now end up in the directory specified in the CSIMCACHE_DIR define. This must also be a directory accessible by the normal web server. By default a directory called "csimcache" will be created in the same directory as the image script itself.
This has the drawback that the directory from where the script is executed must be writable by the process running PHP. Best practice for this is to keep the number of writable directory for PHP down to a minimum and re-use the same directory as is used for the standard cache. This however, require that your system administrator setup that cache directory so that it also accessible by the HTTP server from the htdocs root.
The CheckCSIMCache() method checks the cache for an existing cached version and if found it returns it and halts execution of the script. So, this call should be the first call after the creation of the Graph() and before any heavy work is done to create the image so that you can minimize the execution of the script in the case a match is found.
So, the general structure of a script that uses CSIM and the cache
is
$graph = new Graph(400,300);
// Check cache, 10 min timeout
$graph->CheckCSIMCache("image1",10);
// !! If cached version exists, execution halts here !!
//
// ... Construct the image with heavy DB calls etc, etc
//
$graph->StrokeCSIM();
Please note that you do not need to pass any argument to the final call to StrokeCSIM() as you do when not using the cache.
The clipping algorithm is "perfect" in the sense that for example line plots where the plot area cuts the line between two data points the line will be drawn up to the edge of the plot area. The algorithm used is O(1) in number of data points.
The disabling/enabling of clipping manually is controlled by Graph::SetClipping()
<?php
include (
"../jpgraph.php");
include ("../jpgraph_line.php");
// Some data
$ydata =
array(11,3,
8,12,5
,1,9,
13,5,7
);
// Create the graph. These two calls
are always required
$graph =
new Graph(350,
250,"auto");
$graph->SetScale(
"textlin");
// Create the linear plot
$lineplot
=new LinePlot($ydata);
$lineplot
->SetColor("blue");
// Add the plot to the graph
$graph->Add(
$lineplot);
// Display the graph
$graph->Stroke();
?>
You might note a few things
For example the title of the graph is accessed through the 'Graph::title' property. So to specify a title string you make a call to the 'Set()' method on the title property as in:
$graph->title->Set('Example 2');
So by adding just a few more lines to the previous code we get a graph as shown below.
To achieve this we just needed to add a few more lines. (We only show
the part of example 1 we changed, to look at the full source just click
the [src] link in the caption. )
// Setup margin and titles
$graph->img->SetMargin(40,20,20,40);
$graph->title->Set("Example 2");
$graph->xaxis->title->Set("X-title");
$graph->yaxis->title->Set("Y-title");
Again there are a couple of things you should note here
A nice change would now be to have all the titles in a bold font and
the line plot a little bit thicker and in blue color. Let's do that by
adding the lines
$graph->title->SetFont(FF_FONT1,FS_BOLD);
$graph->yaxis->title->SetFont(FF_FONT1,FS_BOLD);
$graph->xaxis->title->SetFont(FF_FONT1,FS_BOLD);
$lineplot->SetColor("blue");
$lineplot->SetWeight(2); // Two pixel wide
Again please note the consistent interface. To change font you just
have to invoke the SetFont() method on the appropriate object. This
principle is true for most methods you will learn. The methods may be
applied to a variety of objects in JpGraph. So for example it might not
come as a big surprise that to have the Y-axis in red you have to say:
$graph->yaxis->SetColor("red")
or perhaps we also want to make the Y-axis a bit wider by
$graph->yaxis->SetWidth(2)
As a final touch let's add a frame and a drop shadow around the
image since this is by default turned off. This is done with
$graph->SetShadow()
The result of all these modifications are shown below.
For now let's just add a triangle shape marker to our previous graph
by adding the line
$lineplot->mark->SetType(MARK_UTRIANGLE);
This will give the graph as shown below
If you like you can of course both change the size, fill-color and frame color of the chosen plot mark.
The colors of the marks will, if you don't specify them explicitly, follow the line color. Please note that if you want different colors for the marks and the line the call to SetColor() for the marks must be done after the call to the line since the marks color will always be reset to the lines color when you set the line.
To enable the display of the value you just need to call the Show()
method of the value as in
$lineplot->value->Show()
Adding that line to the previous line plot would give the result shown below.
We can of course change both color, font and format of the displayed
value. So for example if we wanted the display values to be dark red,
use a bold font and have a '$' in front we need to add the lines
$lineplot->value->SetColor("darkred");
$lineplot->value->SetFont(FF_FONT1,FS_BOLD);
$lineplot->value->SetFormat("$ %0.1f");
This would then result in the following image
The following lines show how to create the new plot and add it to
the graph (we only show the new lines - not the full script)
$ydata2 =
array(1,19,15,7,22,14,5,9,21,13);
$lineplot2=new LinePlot($ydata2);
$lineplot2->SetColor("orange");
$lineplot2->SetWeight(2);
$graph->Add($lineplot2);
Making these changes to the previous graph script would generate a new graph as illustrated below.
There is a few things worth noting here
The solution to this is to use a second Y-axis with a different scale and add the second plot to this Y-axis instead. Let's take a look at how that is accomplished.
First we need to create a new data array with large values and
secondly we need to specify a scale for the Y2 axis. This is done by
the lines
$y2data =
array(354,200,265,99,111,91,198,225,293,251);
$graph->SetY2Scale("lin");
and finally we create a new line plot and add that to the second Y-axis. Note that we here use a new method, AddY2(), since we want this plot to be added to the second Y-axis. Note that JpGraph will only support two different Y-axis. This is not considered a limitation since using more than two scales in the same graph would make it very difficult to interpret the meaning of the graph.
To make the graph a little bit more esthetic pleasing we use different colors for the different plots and let the two different Y-axis get the same colors as the plots.
The resulting graph is shown below. source)
You will see that each plot type has a 'SetLegend()' method which is
used to name that plot in the legend. SO to name the two plots in the
example we have been working with so far we need to add the lines
$lineplot->SetLegend("Plot 1");
$lineplot2->SetLegend("Plot 2");
to the previous code. The resulting graph is shown below As you can see the legend gets automatically sized depending on how many plots there are that have legend texts to display. By default it is placed with it's top right corner close to the upper right edge of the image. Depending on the image you might want to adjust this or you might want to add a larger margin which is big enough to accompany the legend. Let's do both.
First we increase the right margin and then we place the legend so that it is roughly centered. We will also enlarge the overall image so the plot area doesn't get too squeezed.
To modify the legend you access the 'legend' property of the graph. For a full reference on all the possibilities (changing colors, layout, etc) see class legend in the class reference
For this we use the legends 'SetPos()' method as in
$graph->legend->Pos(0.05,0.5,"right","center");
Doing this small modification will give the result shown below
The above method 'SetPos()' deserves some explanation since it might not be obvious. You specify the position as a fraction of the overall width and height of the entire image. This makes it possible for you to resize the image within disturbing the relative position of the legend. We will later see that the same method is just to place arbitrary text in the image.
To give added flexibility one must also specify to what edge of the legend the position given should be relative to. In the example above we have specified "right" edge on the legend for the for the horizontal positioning and "center" for the vertical position.
This means that the right edge of the legend should be position 5 % of the image width from the right. If you had specified "left" the the legends left edge would be positioned 5 % of the image width from the image left side.
By default the legends in the legend box gets stacked on top of each other. The other possibility is to have them sideways. To adjust this you use the SetLayout() method. Using a horizontal layout with the previous example give the following result.
If the data value is null ("") or the special value "x" then the data point will not be plotted and will leave a gap in the line.
If the data value is "-" then the line will be drawn between the previous and next point in the data ignoring the "-" point.
The following example shows both these possibilities.
You specify that you want the plot to be rendered with this style by calling the method SetStepStyle() on the lineplot.
include("jpgraph_log.php");
on the top of your code. To Illustrate how to use a logarithmic
scale let's make the right Y scale in the previous example a
logarithmic scale. This is done by the line
$graph->SetY2Scale("log");
This will then give the following result
You can of course also use a logarithmic X-scale as well. The following example shows this.
Even though we have so far only shown line graphs logarithmic scale can also be used for bar, error, scatter plots as well. Even radar plots supports the use of logarithmic plots. The following example shows how to use a logarithmic scale for a bar graph.
The normal practice for text scale is to specify text strings as labels instead as the default natural numbers. You can specify text strings for the labels by calling the SetTickLabels() method on the Axis.
To specify the scale you use the SetScale() method. A few examples might help clarify this.
To specify the scale for the Y2 axis you use the SetY2Scale() Since you only specify one axis you only specify "half" of the string in the previous examples. So to set a logarithmic Y2 scale you will call SetY2Scale("log");'; ShowCodeSnippet($t); ?>
The grid is modified by accessing the xgrid (or ygrid) component of
the graph. So to display minor grid lines for the Y graph we make the
call
$graph->ygrid->Show(true,true)
The first parameter determines if the grid should be displayed at all and the second parameter determines whether or not the minor grid lines should be displayed.
If you also wanted the grid lines to be displayed for the Y2 axis
you would call
$graph->y2grid->Show(true,true)
Note. In general it is not a good idea to display both the Y and Y2 grid lines since the resulting image becomes difficult to read for a viewer.
We can also enable the X-grid lines with the call
$graph->xgrid->Show(true)
In the above line we will of course only just enable the major grid lines.
To bring all this together we will display a graph with grid lines for both Y and X axis enabled.
Note: If you think the first value of the Y-axis is to close to the first label of the X-axis you have the option of either increasing the margin (with a call to SetLabelMargin() ) or to hide the first label (with a call to HideFirstTickLabel() )
In the example above we have also made use of alphablending (requires GD 2.x or higher). By default the filled grid lines are disabled. To enable this style you have to call the Grid::SetFill() method.
To specify the labels on the scale you make use of the SetTickLabels() method.
To get a localized version of the name of the month you can use a nice feature in JpGraph, the global '$gDateLocal' object which is an instance of the DateLocale
This class has a number of methods to get localized versions of relevant names for dates, (months and weekdays).
So to specify the X-axis with the short form of the month names we
use the construction
$a = $gDateLocale->GetShortMonth();
$graph->xaxis->SetTickLabels($a);
This will, now result in the image displayed below
Note: It is also perfectly legal to override the default labels for the Y (and Y2) axis in the same way, however there is seldom need for that. Please note that the supplied labels will be applied to each major tick label. If there are insufficient number of supplied labels the non-existent positions will have empty labels.
Specifying that we only want, for example, to print every second label on the axis is done by a call to the method SetTextLabelInterval() Which would result in the graph
If the text labels are long (for example full dates) then another way might be to adjust the angle of the text. We could for example choose to rotate the labels on the X-axis by 90 degrees. With the help of the SetLabelAngle()
Which would then result in the image below
Note: The internal fonts which we have been using so only supports 0 or 90 degrees rotation. To use arbitrary angles you must specify TTF fonts. More on fonts later.
In the example below we have also, as an example, specified plot marks (see previous sections).
Note 1. If you add multiple filled line plots to one graph make sure you add the one with the highest Y-values first since it will otherwise overwrite the other plots and they will not be visible. Plots are stroked in the order they are added to the graph, so the graph you want front-most must be added last.
Note 2. When using legends with filled line plot the legend will show the fill color and not the bounding line color.
Note 3. Filled line plots is only supposed to be used with positive values. Filling line plots which have negative data values will probably not have the appearance you expect.
As you can see from the graph above the grid lines are below the filled line graph. If you want the grid lines in front of the graph you can adjust the depth with call to Graph::SetGridDepth() As the following example shows
You may add any number of ordinary line graphs together. If you want to use three line plots in an accumulated line plot graph you write the following code
// First create the individual plots
$p1 = new LinePlot($datay_1);
$p2 = new LinePlot($datay_2);
$p3 = new LinePlot($datay_3);
// Then add them together to form a accumulated plot
$ap = new AccLinePlot(array($p1,$p2,$p3));
// Add the accumulated line plot to the graph
$graph->Add($ap);
You might of course also fill each line plot by adding the lines
$p1->SetFillColor("red");
$p2->SetFillColor("blue");
$p3->SetFillColor("green");
Using some appropriate data this might then give a graph perhaps like the one showed in the figure below
To construct a spline you need both the X and Y coordinates for the known data points.
You start by constructing a new Spline instance. To
get access to the Spline class you must first remember to include the
file "jpgraph_regstat.php". You instantiate this class by calling it
with your two known data arrays (X and Y) as follows.
$spline = new Spline($xdata,$ydata);
This call initializes the spline with the data points you have. These data points are also known as Control points for the spline. This helper class doesn't draw any line itself. Instead it is merely used to get a new (larger) data array which have all the interpolated values. You then use these new value in your plot. This way give you great flexibility in how you want to use this interpolated data.
Continuing the above line we now use the Spline::Get()
method to get an interpolated array containing a specified number of
points. So for example the line
list($sdatax,$sdatay) =
$spline->Get(50);
Will construct the two new data arrays '$sdatax' and '$sdatay' which contains 50 data points. These two arrays are constructed from the control point we specified when we created the '$spline' object.
You would then use these two new data array in exactly the same way as you would form ordinary data vectors.
The following example illustrates this
Note: In order to make the example more interesting we actually use two plots. First a line plot to get the smooth curve and then a standard scatter plot which is used to illustrate where the control points are.
$lineplot->mark->SetColor("red");
To choose between the different plot marks you call the PlotMark::SetType() method with the correct define to choose the plot type you want to use.
The simple shape type of plot marks are
$lineplot->mark->SetTYPE(MARK_IMG,"myimage.jpg",1.5);
If you want to use one of the built-in images the following images are available. Please note that not all images are available in all possible colors. The available colors for each image is listed below.
The following shape (the first class) plot marks are available
For the second class (built-in images) the following table list the different images as well as what color they are available in. For the built-in images you specify the color with the second argument.
Note that some of the images are available in different sizes. The reason is that even though you can scale them by the third argument there is a visual degradation to scale an image larger than it's original size since some pixels needs to be interpolated. Reducing the size with a scale < 1.0 gives much better visual apperance.
The scaling works with both GD 1 and GD 2 but with GD 2 the quality of the scaling is much better.
Built-in images and available colors:
Type | Description | Colors |
---|---|---|
MARK_IMG_PUSHPIN, MARK_IMG_SPUSHPIN | Push-pin image | 'red','blue','green','pink','orange' |
MARK_IMG_LPUSHPIN | A larger Push-pin image | 'red','blue','green','pink','orange' |
MARK_IMG_BALL, MARK_IMAGE_SBALL | A round 3D rendered ball | 'bluegreen','cyan','darkgray','greengray', 'gray','graypurple','green','greenblue','lightblue', 'lightred','navy','orange','purple','red','yellow' |
MARK_IMAGE_MBALL | A medium sized round 3D rendered ball | 'blue','bluegreen','brown','cyan', 'darkgray','greengray','gray','green', 'greenblue','lightblue','lightred', 'purple','red','white','yellow' |
MARK_IMAGE_LBALL | A large sized round 3D rendered ball | 'blue','lightblue','brown','darkgreen', 'green','purple','red','gray','yellow','silver','gray' |
MARK_IMAGE_SQUARE | A 3D rendered square | 'bluegreen','blue','green', 'lightblue','orange','purple','red','yellow' |
MARK_IMG_STAR | A 3D rendered star image | 'bluegreen','lightblue','purple','blue','green','pink','red','yellow' |
MARK_IMG_DIAMOND | A 3D rendered diamond | 'lightblue','darkblue','gray', 'blue','pink','purple','red','yellow' |
MARK_IMG_BEVEL | A 3D rendered bevel style round ring | 'green','purple','orange','red','yellow' |
Using bar plots is quite straightforward and works in much the same
way as line plots which you are already familiar with from the previous
examples. Assuming you have a data array consisting of the values
[12,8,19,3,10,5] and you want to display them as a bar plot. This is
the simplest way to do this:
$datay=array(12,8,19,3,10,5);
$bplot = new BarPlot($datay);
$graph->Add($bplot);
If you compare this to the previous line examples you can see that the only change necessary was that instead of creating a new line plot (via the new LinePlot(...) call) we used the statement new BarPplot().
The other change we should do is to make sure the X-axis have an text-scale (it is perfectly fine to use a linear X-scale but in most cases this is not the effect you want when you use a bar graph, see more below). With this two simple change we will now get a bar graph as displayed in the following image You can of course modify the appearance of the bar graph. So for example to change the fill color you would use the BarPlot::SetFillColor() method. Making this small change to the previous example would give the expected effect as can be seen in the next example. Sidebar: You should note from the previous two graphs that slight change in appearance for the X-scale. The bar graphs gets automatically centered between the tick marks when using as text x-scale. If you were to use a linear scale they would instead start at the left edge of the X-axis and the X-axis would be labeled with a linear scale. As is illustrated in the (small) example below
To set the width in fraction you use the method SetWidth() and to set the width in pixels you use the SetAbsWidth()
As an example let's take the previous example and set the width to 100% of the distance between the ticks. The example will now become
$barplot->value->Show();
Will enable the values in it's simplest form and will give the result
You cane see a small nuisance in this graph. The auto scaling
algorithm chooses quite tight limits for the scale so that the bars
just fit. Adding the value on top of the bar makes it collide with the
top of the graph. To remedy this we tell the auto scaling algorithm to
allow for more "grace" space at the top of the scale by using the
method
SetGrace() which is used to tell the scale to add a percentage (of
the total scale span) more space to either one end or both ends of the
scale. In this case we add 20% more space at the top to make more room
for the values with the line
$graph->yaxis->scale->SetGrace(20);
This will then give the graph as shown below
You can also adjust the general position of the value in respect to the bar by using the BarPlot::SetValuePos() method. You can set the position to either 'top' (the default) , 'center' or 'bottom'. The graph below shows the value being positioned in the center. In this example we have also adjusted the format to just display the value as an integer without any decimals.
It is also possible to specify a more fine grained control on how you want the values presented. You can for example, rotate them, change font, change color. It is also possible to adjust the actual value displayed by either using a printf()-type format string or with the more advanced technique of a format callback routine.
To show what you can do we just give another example for you to examine without much further explanations. Just remember that to have text at an angle other than 0 or 90 degrees we have to use TTF fonts. Even though we haven't explained the SetFont() method it should be fairly obvious.
// Create the bar plots
$b1plot = new BarPlot($data1y);
$b1plot->SetFillColor("orange");
$b2plot = new BarPlot($data2y);
$b2plot->SetFillColor("blue");
// Create the grouped bar plot
$gbplot = new GroupBarPlot(array($b1plot,$b2plot));
// ...and add it to the graPH
$graph->Add($gbplot);
The following example illustrates this type of graph
There is no limit on the number of plots you may group together.
If you use the SetWidth() method on the GroupBarPlot() this will affect the total width used by all the added plots. Each individual bar width will be the same for all added bars. The default width for grouped bar is 70%.
Setting the grouped with to 0.9 would result in the image below.
You create accumulated bar plots in the same way as grouped bar plots by first creating a number of ordinary bar plots that are then aggregated with a call to AccBarPlot();
An example makes this clear. Let's use the same data as in the two examples above but instead of grouping the bars we accumulate (or stack) them. The code would be very similar (actually only one line has to change)
// Create all the 4 bar plots
$b1plot = new BarPlot($data1y);
$b1plot->SetFillColor("orange");
$b2plot = new BarPlot($data2y);
$b2plot->SetFillColor("blue");
$b3plot = new BarPlot($data3y);
$b3plot->SetFillColor("green");
$b4plot = new BarPlot($data4y);
$b4plot->SetFillColor("brown");
// Create the accumulated bar plots
$ab1plot = new AccBarPlot(array($b1plot,$b2plot));
$ab2plot = new AccBarPlot(array($b3plot,$b4plot));
// Create the grouped bar plot
$gbplot = new GroupBarPlot(array($ab1plot,$ab2plot));
// ...and add it to the graph
$graph->Add($gbplot);
Putting this together in an example would then produce the graph as shown below
The example below shows a simple example of this
In order to achieve this effect you should study the above example carefully and you might notice two things
// Since we swap width for height (since
we rotate it 90 degrees)
// we have to adjust the margin to take into account for that
$top = 50;
$bottom = 30;
$left = 50;
$right = 20;
$adj = ($height-$width)/2;
$graph->SetMargin($top-$adj,$bottom-$adj,$right+$adj,$left+$adj);
In the final example which is almost similar to the two first we illustrate the use of labels with more than one line.
Color gradient fill fills a rectangle with a smooth transition between two colors. In what direction the transition goes (from left to right, down and up, from the middle and out etc) is determined by the style of the gradient fill. JpGraph currently supports 7 different styles. All supported styles are displayed in the figure below.
When using gradient fills there are a couple of caveats you should be aware of:
I this example we defined two areas along the X-axis to be filled. You can add filled areas by using the method AddArea() and specifying range and color for the filled area.
Before you can use error plots you must remember to include the file "jpgraph_error.php" in your script.
The following example illustrates a simple error bar. We will have 5 points, so we need 10 Y-values. We also would like the error bars to be red and 2 pixels wide. All this is accomplished by creating an ErrorPlot() in much the same way as, for example, a normal line plot. Doing this would now give the example shown below.
You might notice that there is one displeasing esthetic quality of this graph. The X-scale is just wide enough to just accompany the number of error bars and hence the first bar is drawn on the Y-axis and the and last bar just at the edge of the plot area. To adjust this you might call the SetCenter() method which will adjust the X-scale so it does not use the full width of the X-axis.
The following example illustrates the use of this feature by applying this technique to the previous example
To control the various properties of the line drawn the "line"
property of the error line plot may be accessed. So, for example, if
you want the line to be 2 pixels wide and blue you would have to add
the following two lines
$elplot->line->SetWeight(2);
$elplot->line->SetColor("blue");
to generate the graph as shown below
You may of course add legends to none, one or both of the line types
in the above graph. So for example if we wanted the legend "Min/Max"
for the red error bars and a legend "Average" for the blue line you
would have to add the lines
$errplot->SetLegend("Min/Max");
$errplot->line->SetLegend("Average");
The resulting graph will now look like (note that we are using the default placement of the legend box)
Even though you would normally supply X-coordinates it is still perfectly possible to use a text-scale for X-coordinates to just enumerate the points. This is especially useful when using the "Impulse" type of scatter plot as is shown below.
Scatter pots are created by including the jpgraph extension "jpgraph_scatter.php" and then creating an instance of plot type of ScatterPlot(). To specify the mark you want to use you access the mark with the instance variable "mark" in the scatter plot. The default is to use an unfilled small circle.
To create a scatter plot you will create an instance
A simple example using just default values will illustrate this
We can easily adjust the size and colors for the markers to get another effect as shown below
Another possible variant of scatter plot is impulse-scatter plots. This is a variant of normal scatter plot where each mark have a line from the mark to the Y=0 base line. To change a scatter plot into an impulse scatter plot you have to call the method SetImpuls() on the scatter plot.
This type of plots are often used to illustrate signals in conjunction with digital signal processing. The following two examples illustrates simple use of impulse plots.
The next example shows how to modify the color and width of the impulse plot
To create a field plot you create an instance of FieldPlot in the same way as you created a normal scatter plot. The arguments to this method are Y-coordinate, X-coordinate and angle. To specify a callback you use FieldPlot::SetCallback()
The following example (and code) illustrates the usage of the field plot type.
In addition to the parameters mentioned above you can also adjust both the general size of the arrow and also the specific size of the arrowhead. The arrow size is specified in pixels and the arrow head is specified as an integers between 0 and 10. These sizes are specified with a call to FieldPlot::arrow::SetSize()
The figure below illustrates a sample Stock chart plot
For this type of plot the Y-data array must be consist of a number of quadruples of data where each quadruple consists of (open,close,min,max). The open and close values determine the min max for the middle bar and the min,max determine the end points of the "error-lines" at the top and bottom of of each bar.
Note that the data follows the following rules
You can specify the width of the bar by setting the width (in pixels) with a call to the method SetWidth()
The final variation of stock plots you can have is to determine whether or not the end point for the min,max lines should have the horizontal line marking the end of the line or not. This can be adjusted with a call to method HideEndLine().
You may modify the median line color for positive and negative data points / bars by using the SetMedianColor() method.
Note: These plot types, though normally used without explicit X-values, can of course handle a supplied X-coordinate array without any problem.
To start simple we just mix a filled line plot with a non-filled line plot as the following example shows.
Let's now go to something a little bit more complicated. How to mix bar and line graphs. Let's just take one of our previous bar graphs and add a line plot to it and see what happens.
Not too bad. But we can't see the line so we change the order in which we add the lines to the graph and sees what happens.
If you want the line points to be aligned in the center of the bars you can accomplish this is two ways.
If you use a text scale then you need to call the LinePlot::SetBarCenter()
You can also use an integer scale. This places both the bar and the line points centered at the tick marks. As the following example will show
Note: In this example we also have illustrated the fact that you can add text labels to a linear (or integer) scales as well.
As a final example we show how you can combine a scatter plot and a line plot which could be used to illustrate a regression line fitting.
To specify a manual scale you have to add arguments to the standard Graph::SetScale() method.
So to specify that you want an Y-scale between 0 and 100 you need to
write
$graph->SetScale("textlin",0,100);
When you specify a scale manually there is one additional thing you need to decide. How the tick marks should be positioned. You have three choices
$graph->SetScale("textlin",0,100);
$graph->yscale->ticks->Set(10,5);
Will set the major tick marks every at 0,10,20,.. And every minor tick mark in between (0,5,10,15,20,25,...).
In the following we will assume that all data points are specified by a tuple where the date/time is specified as a timestamp in second in the same format as is returned by the PHP function time().
The trick here is to use a label formatting callback routine which gets called to format each label on the scale.
What we do is that we specify that the X-scale should be an ordinary "int" scale (remember that the data values are timestamps which are integers). We then install our custom label callback (with a call to SetLabelFormatCallback()) which given a timestamp formats it to a suitable human readable form. In our example we will use the PHP function Date() for this purpose.
The callback we use will be
// The callback that converts timestamp
to minutes and seconds
function TimeCallback($aVal) {
return Date('H:i:s',$aVal);
}
Using some random data we can now generate the following graph
In the above example we have specified the X-scale manually to make sure that the min/max values on the X-axis exactly matches the min/max x-data values.
As a remainder; Text scale is meant to be used on the X-axis when the X-axis doesn't have a numeric value, i.e you are only interested in linear ordering of the data. If you don't specify the labels manually they will be set automatically starting from 1 as the example below shows.
To specify the labels on the X-axis as suitable text strings you call the method Axis::SetTickLabels() with an array containing the text-labels. If there are more data points than labels the non-specified labels will be given their ordinal number. If we augment the previous example with the name of the month we get the following new example
What happen now if we have a larger number of bars? Let's try with 25 bars and see what result we get.
Not all to impressive. The labels are to close and they overlap. Hence it is not a good idea to display every label. To adjust what labels are to be displayed you use the SetTextLabelInterval() method. The argument to this method is the interval between text labels. So to display only every 3 month you would add the line
$graph->xaxis->SetTextLabelIntervall(3)
Which would give the result shown below
Much better, quite readable.
If we have an even larger data set it might not longer be meaningful to display all the tick marks since they would simple become to close. In JpGraph there is a possibility to specify that you only would like every n:th tick mark to be visible ( SetTextTickIntervall() ). For bar graphs using text scale however, that might not be such a good idea since the tick marks are between the bars and the labels centered under the bars. If we only were to display, say, every 3 tick mark it wouldn't look to good. Not that we can't do it, as the example below shows, but it just doesn't look very good.
A better way to handle large data set is simply to hide the tick marks all together. Tick marks may be hidden by calling the method Axis::HideTicks(); If we hide all the ticks on the X-axis we will get the result shown below
To add text you have to create one or more instances of the Text() object and then add the text object to the graph with the AddText() method.
The position of these text boxes are given as fraction of the width and height of the graph. When you are positioning these text boxes you might also choose what part of the text box should be considered the anchor point for the position you specify.
By default the anchor point is the upper left corner of the bounding box for the text.
To show some ways of positioning the text we use a very simple bar
graph not to distract from the text. We first just add a single text
line with most of the settings their default value by adding the
following lines to the graph
$txt=new Text("This is a text");
$txt->Pos(0,0);
$txt->SetColor("red");
$graph->AddText($txt);
The result is shown below.
Not too exiting. Let's make it more interesting by having a background color, using larger fonts and framing the text box and adding a drop shadow to the text box by using the methods SetBox() and SetBox()
That's better. Now we get some attention. If you want to add a text with several lines you just need to separate the lines with a newline ('\n' character). The default paragraph alignment is left edge but you can also use right and center alignment.
As an illustration let's add a couple of more lines to the previous text, center the text box in the middle of the graph and also use centered paragraph alignment for the text. To adjust the paragraph alignment of the text you have to use the Text::ParagraphAlign()
Of course there is no limit to the number of text string you can add to the graph.
From version 1.12 it is also possible to add text strings to a graph using the scale coordinates instead. This is accomplished by using the Text::SetScalePos() Which is completely analog to SetPos() with the only difference that the positions given are interpretated as scale values instead of fractions of the width and height.
The only thing you need to think of is that you probably want to add some extra margin to make room for the titles (using Graph::SetMargin() )
The individual positioning of these titles are done automatically and will adjust to the font size being used.
If you for, esthetic reasons, would like increase the distance from the top where the title is positioned (or the intra distance between title and sub title) you can use the Text::SetMargin() method. For example the line
$graph->title->SetMargin(20);
will set the distance between the top of the title string and the top of the graph to 20 pixels. If you instead call the SetMargin() method for the subtitle it will adjust the distance between the top of the subtitle and the bottom of the title.
The titles will be positioned at the top and be centered in the graph. Each of these titles may have multiple lines each separated by a "\n" (newline) character. By default the paragraph alignment for each title is centered but may of course be changed (using the ParagraphAlign()) method.
Each graph can also have a footer. This footer is actually three footers. Left, center and right. The 'left' footer is aligned to the left, the 'center' at the bottom center and the right to the right.
Each of these three positions is a standard Text object which means you can change color, font and size as you please individually on each of these footer positions.
You access the footer through the Graph::footer property as the following example shows
$graph->footer->left->Set("(C) 2002
KXY");
$graph->footer->center->Set("CONFIDENTIAL");
$graph->footer->center->SetColor("red");
$graph->footer->center->SetFont(FF_FONT2,FS_BOLD);
$graph->footer->right->Set("19 Aug 2002");
You can access the tab using the 'tabtitle' property of the graph.
The following figure shows an example of how this can look.
As usual you have full freedom to specify font and colors for this type of title. Please see the class reference regarding GraphTabTitle() for more information.
To use a specific image as the background you just have to use the method Graph::SetBackgroundImage() The arguments specify file-name, how the image should be positioned in the graph and finally the format of the image (if it is in JPG, PNG or GIF) format. If the format is specified as "auto" (the default) then the appropriate image format will be determined from the extension of the image file.
The file name is of course obvious but the second argument might not be. This arguments determine how the image should be copied onto the graph image. You can specify three different variants here
You might often find yourself wanting to use a background image as a "waterstamp". This usually means taking the original image, import it to some image editing program and then "bleaching" the color saturation, reducing the contrast and so on. Finally you save the modified image which you then use as a background image.
This whole process can be automatically accomplished in JpGraph by using the method Graph::AdjBackgroundImage() which allow you to adjust color saturation, brightness and contrast of the background image.
For example, in the image below I have used the settings
$graph->AdjBackgroundImage(...)
to achieve the "watercolor" effect to avoid the image being too intrusive in the graph.
You specify a color gradient background by calling the Graph::SetBackgroundGradient() method. All details are available in the class reference (follow the link above). We finally give a quick example on what kind of effect you can achieve using this feature.
Finally we like to mention that in the "/utils/misc/" directory you will find a small utility script called "mkgrad.php". Running this script presents you with a UI that makes it a breeze to create a gradient image on it's own.
The UI for the utility is so obvious that we won't discuss it
further, we just show it below. The UI for the mkgrad.php utility
In the example below I have used this utility to get a more interesting plot area.
This callback function will get called with the current Y-value (for the plotmark) as it's argument. As return value the callback function must return an array containing three (possible null) values. The values returned must be
The callback must be a global function and is installed with a call to PlotMark::SetCallback()
So for example to install a callback that changes the fill color for all marks with a (Y) value higher than 90 you could add the lines
90) $fcolor="red" else $fcolor=""; return array("","",$fcolor); } ... $plot->mark->SetCallback("MarkCallback"); ...'; ShowCodeSnippet($t); ?>
As you can see in the above example we have left some of the return values blank. Doing this will just ignore any change of these value and use the global settings for the plotmarks.
If you also let the (Y) value affect the size of the plot marks you can get what is sometimes known as a "balloon plot". The example below is basically a scatter plot that uses filled circles to mark the points. A format callback is then used to change the color and size depending on the Y-value for each plot.
The slight complication with general rotation is that the margins also rotates, this means that if you rotate a graph 90 degrees the left margin in the image was originally the bottom margin. In additional by default the center of the rotation is the center of the plot area and not the entire image (if all the margins are symmetrical then they will of course coincide). This means that depending on your margin the center of the rotation will move. You can read more about this and how to manually set the center for rotation in the section about rotation, 10.2
This is just a slight inconvenience which you have to take into account when you need to set an explicit margin with a call to Graph::SetMargin()
However, in order to make a rotation of 90 degrees much easier you can easily rotate a graph 90 degrees and set the correct margin with a call to Graph::Set90AndMargin() The parameter to this method lets you specify the margins as you will see them in the image without having to think of what becomes what after the rotation.
So, the only thing you need to do is call this method and then the graph will have been rotated 90 degrees.
In addition to the standard positioning you may also use the two special position markers "min" and "max". This will position the axis at the minimum (or maximum) position of the other axis.
For example, to make sure that the X-axis is always at the bottom of the graph (at lowest possible Y-value) you would have to add the line
$graph->xaxis->SetPos("min");
To change the color and width of the axis you have to make use of the Axis::SetColor() and Axis::SetWeight() methods.
You might also want to add titles to the axis. This is done through the Axis::SetTitle() method. This is actually just a shortcut for accessing the title property direct. Axis::title::Set() which also allow you to set the alignment in one call.
By default the position of the title is to the far right for the X-axis and in the middle (and 90 degrees rotated) for the Y-axis.
You can adjust the position of the title with the help of the second argument to the Axis::SetTitle() method.
The possible positions are "high","middle" and "low" which refers to the scale values on the axis.
One common modification you might want to do to the title is to increase the margin between the axis and the actual title. This is often necessary to do for the Y-axis if the values displayed are large. You may adjust the distance (in pixels) between the axis and the title by using the method Axis::SetTitleMargin()
So for example to increase the margin on the Y-axis you might add the line
$graph->yaxis->SetTitleMargin(40);
to your code.
Finally we mention something about the positioning of tick marks and labels on the axis. You have the possibility to choose what side of the axis the tick marks and the labels should be at. For the X-axis this can be specified as either on the the top (inside the plot area) or at bottom (outside of the plotarea). In the same way you can specify for the Y-axis if the labels ( or ticks) should be on the left or right side.
To adjust the label positioning you have to use the method Axis::SetTitleSide() and to adjust the position of the tick mark you have to use the method SetTickSide()
$graph->xaxis->SetLabelPos(SIDE_UP);
$graph->xaxis->SetTickSide(SIDE_DOWN);
This technique is for example used if you position the X-axis at the top of the graph as the following example shows.
Before we continue we show a small example to illustrate this feature
The example above shows the basic configuration. There are now several modifications you may do to these axis like
to adjust the actual label format (like font, color, angle) you need to access the Axis::SetFont() and the Axis::SetColor() methods. If you investigate the Axis class you will discover more methods to adjust the many aspects of the axis layout.
As a final note we also mention the methods Axis::SetLabelAlign() and Axis::SetLabelAngle() This first method is really only mentioned here for completeness since it is mostly used for internal purposes. However on some occasion you might want to adjust the alignment of the labels. By default they are centered in respect to the tick mark. By using the method you might override this positioning should you choose to do so.
The second of these methods adjusts the angle of the label in regards to the axis. This is very useful for X-axis that have long labels.
An inverted Y-scale has the lowest number at the top and the scale values increases downwards.
Even though JpGraph doesn't directly support this feature it is quite easy to achieve with just a few extra lines of code in your image script.
Before we continue we give an example of what we are referring to.
Two achieve this effect there are two simple steps to take:
However you might sometime want to add some extra to the minimum and maximum values so that there is some "air" in the graph between the end of the scale values and the extreme points in the graphs. This can be done by adding a "grace" percentage to the scale. So for example adding 10% to the y-scale in the image above is done by calling the SetGrace() method on the yscale as in
$graph->yaxis->scale->SetGrace(10,10);
These lines add a minimum of 10% to the top and bottom values of the scale. Note that we say "minimum" since depending on the specific tick values choose this might be a little bit more to make the end of the scale fall on an even tick mark.
Adding this line to the previous graph will result in the following example
Since we haven't adjusted the position of the X-axis it will remain at Y=0 which might not necessary be what we would like so we therefor also add the line
$graph->xaxis->SetPos("min");
So that the X-axis always will remain at the lowest possible Y-value. Doing this will then result in the example below
In order to access this functionality you must first make sure that you include the additional library file jpgraph_plotband.php
At the time of this writing (current as of JpGraph 1.8) the table below illustrates the 8 basic types of patterns available. We will shortly show you how you can customize these patterns, To keep these examples clear we have only used one pattern in each figure.
To add a one of these patterns to your graph you need to call the method PlotBand::PlotBand() The arguments is fairly easy to understand. The pattern you would like to use is specified by using the correct constant. You can see the name of the correct constants in the figures above. You also need to specify if the band should stretch along the vertical or horizontal axis as well as the min and max coordinates for the band. As coordinates you may also use the special values "min" and "max" which automatically sets the value to the minimum/maximum value of the scale. The specified numeric value will be automatically truncated to fit within the plot area.
We don't discuss the other arguments further here, instead we refer you to the class reference.
$band->prect->SetHorizon($aHorizon)
assuming that the band is a 3D plane.
To finish this section we give one final, more creative, example on how to use the bands.
$sline = new
PlotLine(HORIZONTAL,0,"black",2);
$graph->Add($sline);
will add a 2-pixel wide horizontal static line at Y-position zero.
As the first thing you must remember to include the extension module that contains the radar plot. "jpgraph_radar.php".
A very simple radar plot is created by the code
<?php
include (
"../jpgraph.php");
include ("../jpgraph_radar.php");
// Some data to plot
$data =
array(55,80,
46,71,95
);
// Create the graph and the plot
$graph =
new RadarGraph
(250,200,
"auto");
$plot =
new RadarPlot
($data);
// Add the plot and display the graph
$graph->Add(
$plot);
$graph->Stroke();
?>
To change the size and position of the radar graph is similar to the pie plot and you do it by using the methods SetSize() and SetCenter()
If you want a filled radar plot you need to specify the fill color with the method SetFillColor() The following example shows these methods in action
$titles = $gDateLocale->GetShortMonth();
$graph->SetTitles($titles);
As you can see the way radar plot is constructed will assign the titles (and plot points) in a counter-clockwise direction. If you want them in clock-wise order you will have to inverse your input data array as well as the title array.
To specify a legend you (as with the other plot) make use of the SetLegend(); method on each radar plot.
$graph->grid->Show();
$graph->grid->SetLineStyle("dotted");
and would result in the following graph
By design the plot is above the grid line but beneath the axis in image depth, hence some part of the grid lines are hidden.
To have the grid lines more "visible" just change their color, say to, dark red by invoking the SetColor() method on the grid lines which would give the following result
Another simple change we could do would be to just change the background color of the radar graph. This is (not surprisingly) done by a call to the method SetColor() invoked on the graph object.
A simple example of this is shown below
The main difference as compared to the X-Y plots is that to all pie plots are added to the PieGraph() instead of the Graph() object we used for the X-Y graphs we have drawn so far. For this you must first include the "jpgraph_pie.php" in your script (or "jpgraph_pie3d.php" if you want to use 3-dimensional pies).
Below you cane see the code needed to create the simplest possible pie graph just using the default settings.
include ("../jpgraph.php");
include ("../jpgraph_pie.php");
$data = array(40,60,21,33);
$graph = new PieGraph(300,200);
$graph->SetShadow();
$graph->title->Set("A simple Pie plot");
$p1 = new PiePlot($data);
$graph->Add($p1);
$graph->Stroke();
The above code would give the following pie graph
There is a few things worth noting here
The next simplest addition we can do is to add a legend to the pie graph. We do this by using the SetLegends(); method. By adding the legends to the previous example we get the following image
(In the figure above we also moved the center of the pie slightly to the left to make more room for the legend box.)
The text for the legends can also contain printf() style format strings to format a number. This number passed on into this string is either the absolute value of the slice or the percentage value. How to switch between the is describe further down in this chapter.
The next change you might want to change is the size and position of the Pie plot. You can change the size with a call to SetSize(); and the position of the center of the pie plot with a call to SetCenter(); The size can be specified as either an absolute size in pixels or as a fraction of width/height (whatever is the smallest). The position of the pie plot is specified as a fraction of the width and height.
To put the size and positioning API to use we will show how to put several pie plots on the same pie graph. In the following example we have also adjusted the legends of the slice values to use a smaller font.
What we do in this example is quite simple, create 4 pie plots, make them smaller and put them in the four corner of the graph. This will give the result as shown in the following example.
3D Pie plots have the same possibilities as the normal pie plots with the added twist of a 3:rd dimension. You can adjust the perspective angle with the method SetAngle() So for example to make the pie more "flat" you just set it to a smaller angle. Setting the perspective angle to 20 degrees in the previous example will give the following result.
Exploding slices is accomplished by the methods Explode() and ExplodeSlice() The first method is used if you want to explode more than one slices and the second is a shorthand to make it easy to just explode one slice.
For example to explode one slice the default "explode" radius you
would just have to say
$pieplot->ExplodeSlice(1)
The above line would explode the second slice (slices are numbered from 0 and upwards) the default amount. Doing this to the two previous example would result in
$pieplot->SetLabelType("PIE_VALUE_ABS");
Furthermore you could enhance the formatting of the value by either using a printf() style format string (using SetFormat() ) or by providing a formatting function callback (using SetFormatCallback() ) for doing more advanced formatting.
You can also adjust the position of the labels by means of the PiePlot::SetLabelPos() method. The argument to this method is either the fraction of the radius or the string 'auto'. In the latter case JpGraph automatically determines the best position and the the first case The following example illustrates this
If this formatting is not enough you can also "manually" specify the labels for each slice individually. You do this by using the PiePLot::SetLabels() method. This will let you specify individual text strings for each label. In each specification you can also add a printf() formatting specification for a number. The number passed on will be either the absolute value for the slice or the percentage value depending on what was specified in the call to SetLabelType()
The SetLabels() method can also take a second parameter, the label position parameter. This is just a shortcut to the SetLabelPos() as described above. By default the position will be set to 'auto' if not explicitely specified.
Another way is to use one of the pre-defined color "themes". This is just a predefined set of colors that will be used for the slices. You choose what "theme" you like to use with the method ( SetTheme() ) At the time of this writing the available themes are
Another simple change is to remove the border ( or change it's colors ) that separates each slice. This can be done by a call to ShowBorder()
This variant is an extension of the standard PiePlot in the sense that it also have a filled circle in the center. The following example illustrates this
Since the PiePlotC is an extension to the basic pie plot all the normal formatting you can do for pie plots you can also do for the PiePlotC .
The additional formatting only concerns the filled middle circle. You have the option of adjusting size, fill color and all font properties. You perform these operations with the methods
PiePlotC::SetMidColor() | Set fill color of mid circle |
PiePlotC::SetMidSize() | Set size (fraction of radius) |
PiePlotC::SetMidTitle() | Set title string (may be multi-lined) |
PiePlotC::SetMid() | Set all parameters in a single method call |
The next example shows an example with some more innovative formatting. In this example we have :
The scale for the radius can be either linear or logarithmic.
A polar graph is created by creating an instance of PolarGraph::PolarGraph(). The polar graph type inherits all the capabilities of ordinary X-Y graphs, i.e they can have background images, background gradients, tabbed titles and so on.
Polar graphs comes in two basic types, they can either show a full 360 degree graph or a half 180 degree graph. The two examples below show these two basic types of graphs.
By default the scale will be auto scaled depending on the data. You can also specify a manual scale by supplying an extra argument to the SetScale() value. The only difference from the manual scaling with the other X-Y-graphs is that for polar graph you only specify a manual maximum. The minimum will always be 0 for the linear scale and a scaled value of 10 (i.e 1, 0.1, 0.001 and so on) for the logarithmic scale.
The plot is clipped to the plot area so if you specify a smaller scale then the maximum value that part of the plot that are outside the plot area will be clipped.
You select what grid lines to show with a call to PolarAxis::ShowGrid() The two example below shows a logarithmic plot with either just major grid lines or both minor and major grid lines.
For the angle grid lines it is possible to specify the angle division between each grid line with the method PolarAxis::SetAngleStep() You specify the step distance in degrees. By default the step size is 15 degrees.
You can adjust the color with the method PolarAxis::SetColor() ?>
The following example specifies different color for the labels. it also shows that you can add both a radial axis title as well as a tabbed title. In this example we have also chosen not to show the frame around the edge of the plot.
For the radius labels all standard formatting that can be done to the X-Y axis such as format string or format callbacks are supported.
A common modification for polar plots is probably to disable the display the last label when using a 360 degree plot since the last label will "collide" with the plot box around the plot area. It is possible to disable the last label with a call to Axis::HideLastTickLabel() As you can see this has been used in some of the examples in this chapter.
// Start by specifying the proper URL
targets
$targets = array("#1","#2", ....... );
$polarplot = new PoalrPlot($data);
$polarplot->mark->SetType(MARK_SQUARE);
$polarplot->SetCSIMTargets(targets);
$graph->Add($polarplot);
$graph->StrokeCSIM();
The pragmatic view: To keep management of our back and know what we have forgotten
The common view: As a tool to help identify project issues and highlight problem areas.
Basically, Gantt charts are used to show the state of a number of activities (possible grouped) against time.
All it takes to do this (using default values for everything) is the following code.
<?php
include (
"../jpgraph.php");
include ("../jpgraph_gantt.php");
// A new graph with automatic size
$graph =
new GanttGraph
(0,0,
"auto");
// A new activity on row '0'
$activity
= new GanttBar
(0,"Project",
"2001-12-21",
"2002-02-20");
$graph->Add(
$activity);
// Display the Gantt chart
$graph->Stroke();
?>
Let's note a few things with the above image and code:
All that is taken care of in the code below.
<?php
include (
"../jpgraph.php");
include ("../jpgraph_gantt.php");
$graph =
new GanttGraph
(0,0,
"auto");
$graph->SetShadow();
// Add title and subtitle
$graph->title->
Set("A nice
main title");
$graph->title->
SetFont(
FF_ARIAL,
FS_BOLD,12);
$graph->subtitle->
Set("(Draft
version)");
// Show day, week and month scale
$graph->ShowHeaders(
GANTT_HDAY |
GANTT_HWEEK |
GANTT_HMONTH);
// Instead of week number show the
date for the first day in the week
// on the week scale
$graph->scale->
week->SetStyle(WEEKSTYLE_FIRSTDAY);
// Make the week scale font smaller
than the default
$graph->scale->
week->SetFont(FF_FONT0
);
// Use the short name of the month
together with a 2 digit year
// on the month scale
$graph->scale->
month->
SetStyle(
MONTHSTYLE_SHORTNAMEYEAR2);
// Format the bar for the first
activity
// ($row,$title,$startdate,$enddate)
$activity
= new GanttBar
(0,"Project",
"2001-12-21",
"2002-02-20");
// Yellow diagonal line pattern on a
red background
$activity
->SetPattern(BAND_RDIAG,
"yellow");
$activity
->SetFillColor
("red");
// Finally add the bar to the graph
$graph->Add(
$activity);
// ... and display it
$graph->Stroke();
?>
From the above example you might note a few things
// Use the short name of the month
together with a 4 digit year
// on the month scale
$graph->scale->month->SetStyle(MONTHSTYLE_SHORTNAMEYEAR4);
$graph->scale->month->SetTextColor("white");
$graph->scale->month->SetBackgroundColor("blue");
to the code above. The resulting image is shown in Figure 139
To create a Gantt chart you add objects to it. As of this writing you may add the following object by the use of the GanttChart::Add() method
function
GanttGraph($aWidth,$aHeight,$aCachedName,$aTimeOut,$aInline)
The only real difference is that for GanttCharts you can specify one or both of the dimension parameters (width and height) as -1 in which case that dimension will be automatically sized determined by scale and fonts chosen. The following examples shows some possible ways of creating a new graph
It is perfectly legal, and perhaps even desirable to leave "gaps" when laying out bands to group related activities. So, for example you could have three activities/bars at positions 1,2,3 and then another 2 bars at position 6,7 leaving band 0,4,5 empty.
All these "invisible bands" have the same height (equ-spaced). The height of each band is automatically determined and depends on both the method of layout ( as specified by (GanttChart::SetLayout()) and the individual heights of the individual bars and titles. The rules are quite simple:
function
GanttBar($aVPos,$aTitle,$aStart,$aEnd,$aCaption,$aHeight)
<?php $aVPos | The vertical position for the bar, [0..n] | |
<?php $aTitle | Title for the activity | |
<?php $aStart | Start date for the activity given as string, e.g "2001-09-22" | |
<?php $aEnd | End date for activity given as either a date (a string) or as the duration (in days) of the activity, e.g both "2001-10-15" and 20.5 are valid inputs | |
<?php $aCaption | Text string (caption) to appear at the end (right side) of the bar | |
<?php $aHeight | Height of bar given as either a value in range [0,1] in which case this is interpretated as what fraction of the vertical position should the bar occupy. The height can also be given in absolute pixels [1..200] |
Using our previous example we will illustrate this parameter by
changing the position of our 'Project' activity to position 7. Therefor
we change the call to GanttBar() to
$activity = new
GanttBar(7,"Project","2001-12-21","2002-02-20");
and we then get the chart as shown below in Figure 140.
Note that the height of each position (vertical position) will depend on the actual height of the bar.
Specifying the end position may be done in two different ways, either by the end date in the same way as for the start date. The other way is to specify the length of the activity in number of days (and fractions thereof). Examples of valid end dates are:
The full signature for milestones are
function
MileStone($aVPos,$aTitle,$aDate,$aCaption)
<?php $aVPos | The vertical position for the bar, [0..n] | |
<?php $aTitle | Title for the activity | |
<?php $aDate | Date for the milestone | |
<?php $aCaption | Text to the right of the milestone |
$milestone = new MileStone(3,"Code
complete","2001-12-01");
$milestone = new MileStone(3,"Code
complete","2001-12-01","(2001-12-01)");
To change the shape of a milestone to, say a triangle, you use the
SetType() method as in
$milestone->mark->SetType(MARK_DTRIANGLE)
Let's put this into practice and add a milestone to our previous example by adding the following two lines of code which result in Figure 141 shown below.
You may note that by default the title color is red for milestones.
If you like to change this to be instead, say bold black, you would
invoke the SetColor() and SetFont() methods on the title property of
milestones as in
$milestone->title->SetFont(FF_FONT1,FF_BOLD);
$milestone->title->SetColor("black");
and thew result would now (not surprisingly be)
To modify the caption you do exactly the same but act on property
'caption' instead of 'title', i.e.
$milestone->caption->SetFont(FF_FONT1,FF_BOLD);
$milestone->caption->SetColor("black");
It is worth noting that you modify the bar title and caption the exact same way by acting on the 'title' and 'caption' property for the bars.
The full signature for GanttVLine() is
function
GanttVLine($aDate,$aTitle,$aColor,$aWeight,$aStyle)
<?php $aDate | Date for the milestone | |
<?php $aTitle | Title for the line. The title is displayed at the bottom of the line | |
<?php $aColor | Color for the line | |
<?php $aWeight | Line width | |
<?php $aStyle | Line style,"dashed", "dotted" and so on |
$vline = new GanttVLine("2001-12-24");
$vline = new GanttVLine("2001-12-24","Phase 1");
$vline = new GanttVLine("2001-12-24","Phase
1","darkred");
$vline = new GanttVLine("2001-12-24","Phase
1","darkred",5);
$vline = new GanttVLine("2001-12-24","Phase
1","darkred",5,"dotted");
$vline = new
GanttVLine("2001-12-24","Phase 1");
$graph->Add($vline);
and the example (See 143) now becomes
From the above figure you can see that by default the line is drawn at the beginning of the day of the specified date and in a 'dashed' style. This can (of course!) be modified so that the line is drawn/aligned anywhere in the specified day. You modify this by invoking the method SetDayOffset() with an argument specifying the fraction of the day where you want the line positioned.
If you, for example, want to display the line in the middle of the
day just add the line
$vline->SetDayOffset(0.5);
to the previous code and the result will be
As usual you may modify the font, size and color by invoking the appropriate method (SetFont(), SetColor()) on the 'title' property of lines.
The left and right markers are accessed through the two properties 'leftMark' and 'rightMark'. They are both instances of the general 'PlotMark' class which is also used for the milestones (and in line graphs). The 'PlotMark' class supports several different styles, for example, diamond (the default for milestones), filled and unfilled circles, squares, stares, and so on. Please refer to the reference section for a complete listing.
Let's illustrate this by adding a right marker to the previous
example. We will use a style of a filled (red) circle with a white
title, say, "M5". In order to accomplish this we must augment the
previous example with the following lines:
$activity->rightMark->Show();
$activity->rightMark->title->Set("M5");
$activity->rightMark->SetType(MARK_FILLEDCIRCLE);
$activity->rightMark->SetWidth(10);
$activity->rightMark->SetColor("red");
$activity->rightMark->SetFillColor("red");
$activity->rightMark->title->SetFont(FF_ARIAL,FS_BOLD,12);
$activity->rightMark->title->SetColor("white");
This might seem like a lot of lines but this is as complicated as it possible can get. As an illustration I have changed more or less everything that is changeable. I changed the default font, font-color, fill-color, frame-color and width of marker. The two lines only really necessary are the first two, showing the mark and setting a title. You could get away with using default values for the rest of the properties.
The resulting image can be seen in Figure 145 below.
I have deliberately introduced a "strangeness" here. If you compare the two previous examples you can see that the last example is larger than the previous one. Why?
The explanation is simple if you remember that the height of bars are sized relative to the horizontal spacing. The horizontal spacing are based on the highest single bar including title size and, here come the explanation, marker size. The horizontal spacing has grown since the minimum height is now based on 10 points(=the height of the mark). The bar still occupy the same percentage of the height so it seems to have grown.
If this behavior is unwanted it is always possible to specify an
absolute size for the bar heigh, say 8 pixels, with a call
$activity->SetHeight(8);
and achieve the result in Figure 146 below.
It is worth noting that the height reserved for each bar is still the same since we haven't changed the height of the marker and the reserved space is the maximum height used by any bar.
$activity->SetHeight(1.0);
$activity2->SetHeight(1.0);
to the previous example. (Note that a value in the range [0..1] is interpretated as the fraction of the reserved height while a value > 1 is interpretated as the absolute size in pixels.)
Aha.. What we are trying to do doesn't really make sense. Since we
have specified that the bar will always occupy 100% of the available
reserved with there will be no distance between the bars. So what if we
specify the bar as 10 pixel absolute by changing the lines to
$activity->SetHeight(10);
$activity2->SetHeight(10);
we instead get
So what can we actually do? Well if you remember the reserved height
for each bar is the maximum height of all bars including titles. This
guarantees that no two bars will ever overlap. To guarantee that titles
don't end up too close together there is a Vertical Label Margin
which basically specifies some extra "air" in between the titles. The
amount of air is specified in percent of the title height. To set the
margin you use
GanttGraph::SetLabelVMarginFactor($aMargin)
As an example let's set that margin in the previous example to 0 and see what happens.
As you would perhaps expect the two bars just barely touches now since there are no extra margin added. If the two bars hadn't had the extra right marker it would have looked very compressed.
By default the vertical margin is set to 40%.
$graph->ShowHeaders( GANTT_HWEEK |
GANTT_DAY );
If you instead wanted "the big picture" it might be enough to show
year and months by specifying
$graph->ShowHeaders( GANTT_YEAR |
GANTT_MONTH );
You can choose freely the combination of scales that you want, but a chart must at least have one scale of course.
Once you have decided what level of details you need you can then fine tune the exact layout/formatting of each of the enabled scales as described below.
These scale header are all accessed through the graph instance
variables 'scale' as in
$graph->scale->week
or
$graph->scale->day
. All these headers share the following properties.
Show()
Determine if the scale should be shown or not
SetFont()
Font for text in header
SetFontColor()
Specify the color of the header text
SetStyle()
Specify what date format should be used, for example in the week scale it is possible to show either week number, the start date of the week and so on.
SetBackgroundColor()
As it says, the background color for the header
SetFrameWeight()
The line weight of the box around the scale
SetFrameColor()
The line color for the frame
SetTitleVertMargin()
The margin, in percent, below and above the title text
$graph->scale->week->grid->SetColor("red");
Each of the scales also have some specific formatting possibilities as described below.
$graph->ShowHeaders(GANTT_HDAY |
GANTT_HHOUR | GANTT_HMIN);
The code snippet below shows how to set up a minute scale with 30
min interval and some custom colors.
$graph->scale->minute->SetIntervall(30);
$graph->scale->minute->SetBackgroundColor('lightyellow:1.5');
$graph->scale->minute->SetFont(FF_FONT0);
$graph->scale->minute->SetStyle(MINUTESTYLE_MM);
$graph->scale->minute->grid->SetColor('lightgray');
The code snippet below shows hot to set up a hour scale to with 45
minutes interval and some custom colors
$graph->scale->hour->SetBackgroundColor('lightyellow:1.5');
$graph->scale->hour->SetFont(FF_FONT1);
$graph->scale->hour->SetStyle(HOURSTYLE_HMAMPM);
$graph->scale->hour->SetIntervall("0:45");
The example below shows a gantt chart with the day and hour scale enabled
SetWeekendColor()
Set the background color for weekends. (Defaults to light gray)
SetSundayFontColor()
The Sunday font color. (Defaults to red)
UseWeekendBackground()
of the scale, e.g.
$graph->scale->UseWeekendBackground(false);
It might be worth pointing out here that the week number calculation is carried out within JpGraph and does not rely on the underlying OS date libraries. This makes the behavior consistent over several OS:s (at least M$ Windows does not comply to ISO-8601 or supply any way of doing this through the normal libraries, e.g. strftime())
You may modify the week behavior in three ways. You can specify (with SetStyle()) a different date format using the constants
WEEKSTYLE_WNBR
Show week number To further modify the formatting of the actual week
number you can optionally supply a format string with a call to
SetLabelFormatString()
The format of the string should be a standard sprintf() syntax expecting an integer (the week number). By default a 'W' is prefixed to the number.
WEEKSTYLE_FIRSTDAY
Show date of first day in week.
MONTHSTYLE_SHORTNAME
Display the month name in its locale specific short form, i.e Jan, Feb etc
MONTHSTYLE_SHORTNAMEYEAR2
Display the month name in its locale specific short form together with a 2 digit year , i.e Jan '01, Feb '01 etc
MONTHSTYLE_SHORTNAMEYEAR4
Display the month name in its locale specific short form together with a 4 digit year , i.e Jan 2001, Feb 2001 etc
MONTHSTYLE_LONGNAME
Display the month name in its locale specific long name, i.e. January, February
MONTHSTYLE_LONGNAMEYEAR2
Display the month name in its locale specific long name together with a 2 digit year , i.e January '01, February '01 etc
MONTHSTYLE_LONGNAMEYEAR4
Display the month name in its locale specific long name together with a 4 digit year , i.e January 2001, February 2001 etc
Caption text for a bar is specified either when creating a bar or
later by accessing the 'caption' property of bars. So the two lines
$activity = new GanttBar(0,"Activity
1","2001-11-21","2001-12-20","[BS,ER]")
and
$activity->caption->Set("[BS,ER]");
are both ways of specifying the caption "[BS,ER]" for the activity.
Since activity is a standard JpGraph text object you can easily modify
font, color and size with calls to SetFont() and SetColor(), (e.g.
$activity->caption->SetFont(FF_ARIAL,FF_BOLD,9);
The figure below illustrates the use of caption
The properties for the progress indicator are accessed through the 'progress' property and it's methods.
To set the progress for a specific activity you only specify the
percent as a fraction. As in
$activity->progress->Set(0.4)
In Figure 152 the previous example is modified to indicate the progress of each activity by the default progress indicator. A solid bar. To make it clearer I have also modified the caption to reflect the displayed progress. (At the same time I slightly modified the scale headers just for fun).
To specify a different format for the progress you use the
SetPattern() method as in
$activity->progress->SetPattern(BAND_RDIAG,"blue");
In the reference section you can see the exact parameters and all available methods.
So to get the effect we want for a group bar we have to use the two
lines:
$groupbar->leftMark->SetType("MARK_LEFTTRIANGLE");
$groupbar->rightMark->SetType("MARK_RIGHTTRIANGLE")
As of the current version There is not yet any formatting support to accomplish the effect of indentation for the titles so this is accomplished by using a fixed width font and adding spaces in front of the title.
First out is an example to help visualize what we will achieve
To use multiple columns there is two steps. First you need to set the titles (name, color, fonts etc). Thereafter you need to add the title columns for each individual bar.
To set the columns you will have to work with the Activity
information property of the scale. The following code excerpt show
this
$graph->scale->actinfo->SetColTitles(
array('Note','Task','Duration','Start','Finish'),array(30,100));
You will notice two things. We fist specify the titles using an array. We have also specified a second array with the numbers 30 and 100. This is an optional array that specifies the minimum width of, in this case, the first two columns. By default the columns will be wide enough to hold the widesat text string in the column. However for esthetic reasons you might sometimes want to increase the minium width. This is what we have done here for the first two columns.
Furthermore you can also adjust the background colors and the style
and colors of the vertical dividing grid lines. In the previous image
we used the lines
$graph->scale->actinfo->SetBackgroundColor('green:0.5@0.5');
$graph->scale->actinfo->SetFont(FF_ARIAL,FS_NORMAL,10);
$graph->scale->actinfo->vgrid->SetStyle('solid');
$graph->scale->actinfo->vgrid->SetColor('gray');
The style for the grid lines can also be "dashed", "dotted" or
"longdashed" as in other line formatting contexts within the library.
You can also adjust if you would like the small "3D" effect in the
titles. By default this is enabled. You can easily turn this of with a
call to
$graph->scale->actinfo->SetStyle(ACTINFO_2D);
To adjust the colors of the vertical dividing lines in the title the method SetColor() is used as in "$graph->scale->actinfo->SetColor('navy');".
The second thins is to actually populate the columns. This is done (of course) as you add the activity bars to the graph. Previous we just used a string as the title when we wasn't using columns. By simply replacing this string with an array we specify the content of the columns.
For example to specify two column titles we just create a hypothetical Gantt bar as In the full example above we put all this in arrays to make for better coding practice since we create several bars.
In addition to ordinary text you can also add an image or any of the
predefined icons available. In order to add that in a column you first
create an instance of IconImage() and then specify that instance
instead of the text. So in the previous code snippet if we wanted a
"open folder" image in the first column we would change the lines to
$iconopen = new
IconImage(GICON_FOLDEROPEN,0.6);
$title2="";
$bar = new
GanttBar(0,array($iconopen,$title2),"2003-11-23","2003-12-05");
The available builtin icons are
$myicon = IconImage('myicon.png');
If you wonder, the second argument in the IconImage() call is an optional scaling factor which you can use to adjust the size of the image.
$graph->scale->tableTitle->Set('Phase
1');
$graph->scale->tableTitle->SetFont(FF_ARIAL,FS_NORMAL,12);
$graph->scale->SetTableTitleBackground('darkgreen@0.6');
$graph->scale->tableTitle->Show(true);
A full example of this is shown below
$bar->title->SetCSIMTarget(array('sometarget1.html','sometarget1.html'),
array('alttext1','alttext2'));
$graph->scale->tableTitle->Set("(Rev:
1.22)");
$graph->scale->tableTitle->SetFont(FF_FONT1,FS_BOLD);
$graph->scale->SetTableTitleBackground("silver");
$graph->scale->tableTitle->Show();
The example lines above also changes the default white background to silver. Adding these lines to the previous example gives the following result:
From the above example you might notice that the width of the left column (which holds all the titles) have automatically adjusted itself to make the table title fit.
$graph->scale->divider->SetWeight(3);
$graph->scale->divider->SetColor("navy");
$graph->scale->dividerh->SetWeight(3);
$graph->scale->dividerh->SetColor("navy");
The effect of this is shown in Figure 157 below
$graph->SetBox(true,"navy",3)
which will result in a thicker plot box around the area as shown below
Note: You might notice the slight discrepancy in design that here you use a method and in the previous cases accessed a property which you modified. This is the unfortunate affect of over a years development of JpGraph. My own design preference has simply changed over time. For revision 2.x I plan on taking the opportunity to make things like this more conform since I have now convinced myself that this is a better design.
Now when you have a basic understanding of how this works you are ready to appreciate a small helper method. GanttGraph::CreateSimple(). This method takes a few arrays of data which specifies you Gantt chart and then constructs this chart. By using this method you sacrifices a few adjustment possibilities for simplicity. This method is nothing magical it just takes the data for the activities,(start and end date, titles, progress, any constrains and so on) and constructs the activities and adds them to the graph.
The activities are specified in data array which for each activity have the following fields
So for example to create a Gantt chart consisting of two activities which are grouped and a milestone one would have to use something similar to the following code
$data = array(
array(0,ACTYPE_GROUP, "Phase
1", "2001-10-26","2001-11-23",""),
array(1,ACTYPE_NORMAL, " Label
2", "2001-10-26","2001-11-13","[KJ]"),
array(2,ACTYPE_NORMAL, " Label
3", "2001-11-20","2001-11-22","[EP]"),
array(3,ACTYPE_MILESTONE," Phase 1 Done", "2001-11-23","M2") );
// Create the basic graph
$graph = new GanttGraph();
$graph->title->Set("Gantt Graph using CreateSimple()");
// Setup scale
$graph->ShowHeaders(GANTT_HYEAR | GANTT_HMONTH | GANTT_HDAY |
GANTT_HWEEK);
$graph->scale->week->SetStyle(WEEKSTYLE_FIRSTDAY);
// Add the specified activities
$graph->CreateSimple($data);
// .. and stroke the graph
$graph->Stroke();
This will then show up as
You may (slightly) modify the appearance of the simple Gantt charts by means of the methods GanttGraph::SetSimpleFont() and GanttGraph::SetSimpleStyle() But not anything else, remember that the purpose with this way of constructing graphs is to be simple. If you need full advanced control you have to construct all the activities in the "normal" way.
You can also specify constrains and progress for each bar by supplying additional data arrays to GanttGraph::CreateSimple().
You specify the target and the associated "Alt" text for an activity bar by calling the GanttBar::SetCSIMTarget() and GanttBar::SetCSIMAlt()
In a similar way you set the target and Alt texts for the activity
title as the following code extract shows.
$bar->SetCSIMTarget("http://localhost/abc/");
$bar->SetCSIMAlt("Alt Text for the bar");
$bar->title->SetCSIMTarget("http://localhost/abc");
$bar->title->SetCSIMAlt("Alt Text for the title");
The above code assumes that your activity is available in the variable 'bar'. In the example directory there is a complete example of how to use CSIM together with Gantt charts in the "ganttcsimex1.php" file. (Please note that this example makes use of the simplified Gantt chart specification using the CreateSimple() method.
JpGraph support visualizing the following types of constrains
Assume that we start with the Gantt schema as illustrated below
We would now like to add the constrains that the activity "Label 3" cant start before activity "Label 2" has finished and that the milestone "Phase 1 done" is depending on when activity "Label 3" is done.
The principle of adding constrains is that you for each activity you want to have a constrain you have to tell to what other activity this constrain should be to. That other activity is specified by telling on what row that activity lies. Depending on what type of constrain, e.g. Start-to-End, an arrow will now connect the two activities in correct way.
The way to do this is to call the SetConstrain() method on the activity. In this method you specify the type of constrain as well as to what other activity this constrain should be to. If you read the class reference you can also see that you can specify the type and size of arrow used. For now we will just use the default sizes and type.
So for example to add an End-To-Start constrain between "Label 2"
and "Label 3" you could write
$bar2->SetConstrain(2,CONSTRAIN_ENDSTART)
The first parameter in the call above "2" is the row of the target activity (i.e. the row where "Label 3") activity is. In the example below we have added the constrains we wanted.
A note: The actual path followed by the arrow is controlled by some heuristics to make it clear what the constrain is. It has been a design decision that in order to keep the API simple the user has no further detailed controlled on the actual path followed. However, in future version the heuristics may be extended and provide some user-controllable parameters.
$graph->SetDateRange("2001-12-20","2002-01-20");
will show the part of the Gantt chart between the 20 Dec 2001 and 20 of January 2002. Please note that the format depends on the locale setting.
To specifically set a locale you specify the wanted locale with a
locale string (ala standard PHP), for example American English is
specified with the string 'EN_US', British English with 'EN_UK' 'nl_NL'
for Dutch and so on. If your current installation does not support the
specified locale an error message will be given.
$graph->scale->SetDateLocale("se_SE");
The result is displayed below.
In the following I will make the assumption that the reader is familiar with the basic concepts of client side image map in HTML. If you are not familiar you can a) read some book that explains this or b) pay me lots of money to explain it to you :-)
// Image map specification with name "mapname" <MAP NAME=...> ... specification ... </MAP> // Image tag <img src="..." ISMAP USEMAP="mapname">
This poses some interesting questions.
Since we normally call the graphing script directly in the <img> tag how do we get hold of the image map (which is available only in the image script> in this "wrapper" script?
In JpGraph there is actually two ways of solving this.
This of course means that you have to treat an image map returning image script differently from a non-CSIM image script, for example you can't use it directly as the target for the "src" attribute of the <IMG> tag.
What the hotspots represent depends on the type of plot you are doing. The following plot types support image maps.
The two arguments to this method are
You can create an CSIM in two ways
<a href="mycsimscript.html">
This has the drawback that your image page will only contain the
image and nothing else.
<h2> This is an CSIM image </h2>
<?php
include "mycsimscript.php"
?>
$graph->StrokeCSIM('mycsimscript.php')
However, you can apply a small "trick" here. PHP maintain a special
variable called "__FILE__" which is always set to the current file
name. So this means you could use the following construction:
$graph->StrokeCSIM(basename(__FILE__))
This is a better way since you can now rename the file without having to change any code in the file which you otherwise would have to.
| |
| |
|
The fundamental issue we have to solve is that we must be able to call the image script in two modes. When the user includes the image script the StrokeCSIM() method should return the HTML page but when the image script is later called directly in the image tag it must not return an HTML page but rather the actual image.
The way this is solved is by using one HTTP argument which is passed on automatically when we use the image script name in the image-tag.
If you look at the generated HTML you will see that the argument to the src-property of the image tag is not simply the script name but the script name with a additional argument.
In the JpGraph internal code this pre-defined argument is checked for and if it exists the image is send back and not the HTML page.
The name of this argument is defined by a DEFINE() statement in JpGraph. The define is _CSIM_DISPLAY.
An example of the use of this is shown below. With these lines the
image will be written to a file. The script then returns a HTML page
which contains the Client side image map and an img-tag which will
retrieve the previously stored file.
$graph->Stroke("/usr/local/httpd/htdocs/img/image001.png");
echo $graph->GetHTMLImageMap("myimagemap001");
echo "<img src=\"img/image001.png\" ISMAP
USEMAP=\"#myimagemap001\" border=0>";
The anti-aliasing for lines works by "smoothing" out the edges on the line by using a progressive scale of colors interpolated between the background color and the line color.
An example will show that this, quite simple algorithm, gives a reasonable good result. The figures below shows a radar plot with and without anti-aliasing.
One thing you need to keep in mind when deciding to use anti-aliasing is that it could have potentially a dramatic effect on the time it takes to generate the image. Line drawing with anti-aliasing turned on is roughly 8 times slower than the normal line drawing so treat this feature wisely.
Furthermore there are a couple of "gotchas" you should be aware of when using anti-aliasing.
Rotation is probably most used to rotate a graph 90 degrees, for example a bar graph to get the effect of horizontal bars.
By default the center of the rotation will be the center of the plot area, which may or may not coincide with the center of the entire image.
To control the rotation you use the two methods
$graph->image->SetAngle(45);
There is actually a third method that you could use, adding a translation to the graph after the rotation. Since this probably a very little used method we don't discuss it further but refer the reader to the class reference instead Graph:image::SetTranslation()
When you rotate an image you should be aware of that the individual
labels on the axis are not rotated. The design decision behind this is
a) Bit mapped font can't be rotated
b) Maintain readability
Please remember that you may still rotate the labels by calling the Axis::SetLabelAngle() method.
Since the anchor point for labels is by default the optimum for graph at 0 degree you might want to adjust the anchor point and alignment for the labels on the axis to get a better visual appearance on you rotated graph. This is accomplished by the method Axis::SetLabelAlign() For a detailed discussion on how to do this please see the section on horizontal bar graphs, ( Working with bar plots )
The table below shows some examples on different kinds of rotation to give you an idea of how changing the angle and rotation center may be used to generate different effects. The top left graph is the original image. The point of rotation has been marked with a red-cross in each of the images.
Since the rotation, by design, only affects the plot area it is often most effective to use when the color of the margin is the same as the background color.
![]() Brightness=0, contrast=0, saturation = -1 (Original image) | ![]() Brightness=0, contrast=0, saturation = -1 (Black &White image) |
![]() Brightness=0.3, contrast=-0.3, saturation=0 | ![]() Brightness=0.4, contrast=-0.7, saturation=0 |
![]() Brightness=0.4, contrast=-0.7, saturation=-1 | ![]() Brightness=0, contrast=0, saturation=1 |
To enable this feature you can proceed in two ways.
$gJpgBrandTiming=true;
in the beginning of the script.
Country flags can be used in primarily two settings
To specify a country flag as a marker you have to specify the special mark type as one of MARK_FLAG1,MARK_FLAG2,MARK_FLAG3 or MARK_FLAG4
Flags are internally stored in 4 different sizes which is indicated by the number in the mark types. Flags may also be arbitrary scaled when displayed. Since this is partially overlapping functionality you might very well ask why the flags are stored in four different basic sizes. The reason is of course performance. It you only want a very small flag it takes processing time to scale down a large image to, say, a small icon size. At the same time for large flags to be used as background a small original flag might not have enough details to be scaled up to a large size. Hence the reason for storing the flags in 4 different sizes.
The example below shows how to use country flags as markers
To use country flags as background one has to use the method Graph::SetBackgroundCountryFlag(). With this method you can specify both how much of the image should be filled as well as how much of the flag should be mixed into the background.
To see a list of all supported country flags you can run the script "listallcountryflags.php" in the Example directory. This will show you a table with all flags.
The image from icons are taken from a file or as one of the builtin country flags.
You may control how much of the icon should be blended into the background by specifying a percentage (1-100). The example below shows how to mix in the picture of "Tux" into the background of a filled line graph. Note: This example uses alpha blending and will therefore require GD2.
To specify any of the roughly 200 country flags as an icon you first create an empty Icon and then call the IconPlot::SetCountryFlag() with the appropriate parameters. (See the class reference). This is illustrated below by adding the Icelandic flag into the background as an icon
Working with canvas requires more understanding of JpGraph as well as more programming and fine tuning.
You can work with a canvas in different levels of complexity. You can for example work directly with the Image class which provides a large number of primitives for drawing but requires that you use absolute pixel coordinates.
You can also make life a little bit easier by using a canvas scale. This lets you define your own scale on the canvas which often makes it easier by letting you work on a grid you have specified yourself. It also makes it very easy to re-scale you image automatically by just changing your scale. For example to half the size of you drawing you just make the scale twice as large.
To give you some help in working with different canvas you should include the "jpgraph_canvtools.php" file when working on canvases. This is not strictly necessary but it will give you some nice abstraction to help you create your masterpieces.
As another (concrete) example on the use of a canvas the figure below is a listing of font styles available with JpGraph.
Creating a canvas gives you the opportunity draw arbitrary shapes on a "white" piece of paper. Let's first show a simple example were we just draw a text box. We first show you the code which we will walk through
<?php
// $Id: canvasex01.php,v 1.3
2002/10/23 08:17:23 aditus Exp $
include
"../jpgraph.php";
include "../jpgraph_canvas.php";
// Setup a basic canvas we can work
$g =
new CanvasGraph
(400,300,
'auto');
$g->SetMargin(
5,11,6
,11);
$g->SetShadow();
$g->SetMarginColor(
"teal");
// We need to stroke the plotarea and
margin before we add the
// text since we otherwise would overwrite the text.
$g->InitFrame();
// Draw a text box in the middle
$txt="This\nis\na TEXT!!!";
$t = new Text(
$txt,200,10
);
$t->SetFont(
FF_ARIAL,
FS_BOLD,40);
// How should the text box interpret
the coordinates?
$t->Align(
'center','top');
// How should the paragraph be
aligned?
$t->ParagraphAlign(
'center');
// Add a box around the text, white
fill, black border and gray shadow
$t->SetBox(
"white",
"black","gray");
// Stroke the text
$t->Stroke(
$g->img);
// Stroke the graph
$g->Stroke();
?>
We then call the InitFrame() method which actually strokes the margin and plotarea to the graph. Since everything is stroked in the order you issue the commands you must make sure that the graphical objects you want on top is stroked last. This is different from the way you normally work with JpGraph since it queues up all you addition and then makes sure they are stroked in the correct order.
We then create a Text object, setup it's properties, including the absolute screen position where we want the text, and then stroke it. Her it might be a need for a closer explanation of the, perhaps misnamed, method Text::Align() This method states how the text coordinates should be interpreted , i.e when we specify (200,10) as the coordinates for the text paragraph should that be interpreted as the top left corner, bottom-left corner or something else (of the bounding box)? In the code above we have chosen to interpret the X-coordinate as being the center of the bounding box and the Y-coordinate as the top. Hence the text will be aligned so that the (200,100) point in the graph is aligned with the middle of the top line of the paragraphs bounding box.
We also specify that the lines within the paragraph should be centered with a call to Text::ParagraphAlign() Since we also choose to have a box around the text we have to make use of the method Text::SetBox() which is used to specify the fill color, the border color and the shadow color (if you leave out shadow color or set it to '', no shadow will be used).
Now we are ready to stroke the text onto the canvas. In order to do so we must specify the basic Image drawing class we want to use. Without discussing this further we just state that a suitable image class can always be found as the img property of the Graph class.
Finally we are ready to stroke the entire graph, which in effect sends the canvas back to the browser. Below you can see the effect of all this code
$graph->img->Line(0,0,100,100);
To your code. The following example shows some of the graphic primitives you have access to in the Image class
<?php
// $Id: canvasex02.php,v 1.1
2002/08/27 20:08:57 aditus Exp $
include
"../jpgraph.php";
include "../jpgraph_canvas.php";
// Setup a basic canvas we can work
$g =
new CanvasGraph
(400,200,
'auto');
$g->SetMargin(
5,11,6
,11);
$g->SetShadow();
$g->SetMarginColor(
"teal");
// We need to stroke the plotarea and
margin before we add the
// text since we otherwise would overwrite the text.
$g->InitFrame();
// Add a black line
$g->img->
SetColor(
'black');
$g->img->
Line(0,0
,100,100);
// .. and a circle (x,y,diameter)
$g->img->
Circle(100,100
,50);
// .. and a filled circle
(x,y,diameter)
$g->img->
SetColor('red');
$g->img->
FilledCircle(
200,100,50
);
// .. add a rectangle
$g->img->
SetColor(
'green');
$g->img->
FilledRectangle(
10,10,50
,50);
// .. add a filled rounded rectangle
$g->img->
SetColor(
'green');
$g->img->
FilledRoundedRectangle(
300,30,350
,80,10);
// .. with a darker border
$g->img->
SetColor(
'darkgreen');
$g->img->
RoundedRectangle(
300,30,350
,80,10);
// Stroke the graph
$g->Stroke();
?>
We refer you to the class reference to find out what other graphic primitives are available for use.
To help with this you can use a scale for the canvas. This lets you define a "work-space" of your choice. You can for example set the coordinates to be between X:0-10, Y:0-10. This makes it easier to position objects on the canvas. This also has two additional advantages:
To use this type of scaling you must make sure you include the file "jpgraph_canvtools.php" . In addition to the scaling class their are also a couple of other utility classes that may come in handy, especially the Shape class.
Using the scale is quite simple. You first instantiate a scale
object passing the graph as a parameter and then specify the scale you
want to use. This means you need to add the lines
$scale = new CanvasScale($g);
$scale->Set(0,$xmax,0,$ymax);
to your code. You can then use one of the translation methods (for
example
CanvasScale::Translate()) in the canvas scale class to translate
between your world coordinates and the absolute screen coordinates.
This means you could take the code in the example above and just add
the lines, for example,
list($x1,$y1) =
$this->scale->Translate($x1,$y1);
list($x2,$y2) = $this->scale->Translate($x2,$y2);
$g->img->Line($x1,$y1,$x2,$y2);
Since this pattern has to be repeated for every object that has to be drawn it makes good sense to encapsulate this in a separate class. This is exactly why the canvas tools file also have a utility class called Shape This class is mainly a wrapper around the most commonly used methods in the basic Image class (with one important exception) and does all these the translation for you. Please see the class reference for a complete list of the available methods To set up the Shape class you instantiate it with the graphic context and the scale you want to use as argument as in
$shape = new Shape($g,$scale);
You are then ready to use all the methods in the shape class. Using a scale and imitating the previous example we would get the source shown below.
<?php
// $Id: canvasex03.php,v 1.1
2002/08/27 20:08:57 aditus Exp $
include
"../jpgraph.php";
include "../jpgraph_canvas.php";
include "../jpgraph_canvtools.php";
// Define work space
$xmax=20;
$ymax=20;
// Setup a basic canvas we can work
$g =
new CanvasGraph
(400,200,
'auto');
$g->SetMargin(
5,11,6
,11);
$g->SetShadow();
$g->SetMarginColor(
"teal");
// We need to stroke the plotarea and
margin before we add the
// text since we otherwise would overwrite the text.
$g->InitFrame();
// Create a new scale
$scale =
new CanvasScale
($g);
$scale->Set(
0,$xmax,0
,$ymax);
// The shape class is wrapper around
the Imgae class which translates
// the coordinates for us
$shape =
new Shape($g,
$scale);
$shape->SetColor(
'black');
// Add a black line
$shape->SetColor(
'black');
$shape->Line(
0,0,20
,20);
// .. and a circle (x,y,diameter)
$shape->Circle(
5,14,2
);
// .. and a filled circle
(x,y,diameter)
$shape->SetColor(
'red');
$shape->FilledCircle(
11,8,3
);
// .. add a rectangle
$shape->SetColor(
'green');
$shape->FilledRectangle(15,
8,19,14
);
// .. add a filled rounded rectangle
$shape->SetColor(
'green');
$shape->FilledRoundedRectangle(2,
3,8,6
);
// .. with a darker border
$shape->SetColor(
'darkgreen');
$shape->RoundedRectangle(2,
3,8,6
);
// Stroke the graph
$g->Stroke();
?>
If we like to make a smaller image we could just change the image size and everything will be rescaled without any further code changes. SO for example making the image half the size would give the result
If we instead wanted to keep the image size but shrink the shapes we could just make the scale twice as large which would result in
We previously mentioned that the Shape class was a wrapper around the image class with one exception. So what is the exception? Well, glad you asked. The exception is that it contain an additional method which draws an "indented rectangle". An indented rectangle is a rectangle where one of it's four corners have been moved into the rectangle. You create an indented rectangle by calling either Shape::IndentedRectangle() or A few examples illustrates what this shape looks like.
As a final note we mention the class CanvasRectangleText Which can be used to add a text with a rounded rectangle (possibly filled) onto the canvas. The previous example where all the available fonts were drawn were using this class. We don't describe it further but refer the interested reader to the class reference and the 'listfontsex1.php' example file.
The library php file "utils/misc/imgdbschema.php" included in the distribution contains some utility classes to make the drawing of table schemes easier. It contains two basic classes, Class ImgDBTable and Class ImgDBSchema. The first class understand how to draw an image illustrating a single table. The second class is responsible for automatically extract all the relevant information from a DB to draw a complete DB Schema.
Before going into this a little bit more we show what an example of this might look like.
Before going on it should be noted that the ImgDBSchema assumes that the DB can be accessed through a DB abstraction layer modeled after the abstraction layer available in the 'jpdb.php' file in the DDDA architecture. This abstraction layer assumes a MySQL database in the bottom. This specific dependency of this particular abstraction layer is the reason I have not included these classes in the generic canvas tools file.
The second thing you should note that this library does not contain a complete automatic-layout engine but rather a very simple automatic system which, if nothing else is specified, just puts the table in a rectangular grid. A complete graph layout engine would simple be to much to write in this context. This is also a very difficult optimization problem and sofar not even any of the professional programs I have seen that tries this can achieve a satisfactory layout without manual intervention.
The critical lines in the code to generate the above graph is
$tblposadj=array($tlo,0,$tblwidth+$tlo+2,0,2*$tblwidth+$tlo+4,0,-1,16,-1,16);
$dbschema = new
ImgDBSchema("jpgraph_doc","FormatTblName","FormatFldName");
$dbschema->SetMargin($leftm,$topm);
$dbschema->SetTableWidth($tblwidth);
$dbschema->Stroke($this->img,$this->iscale,$tblposadj);
The rest of the code in the file is just to setup the canvas, add an indented rectangle to group some tables and generate a footer with the date and time this image was generated.
The first line instantiates a new ImgDBSCheme layout engine asking it to draw an image for the database 'jpgraph_doc'. The following two arguments specify two callback functions for formatting the text for header and each field in a table.
The next line specify the top left margin where the drawing of the tables should be started.
The third line specify the width of a single table. The final lines starts the engine and draws all tables in the database to the canvas. The final argument requires some further explanation. This is an offset (x,y) from the top left corner how each individual table should be positioned. If the value is -1 indicates that the default value should be used. If this array is not specified then the tables will simple arranged line by line.
The full source code for drawing this DB schema example is shown below.
<?php
/*=======================================================================
// File: DBSCHEMAEX1.PHP
// Description: Draw a DB schema of the DDDA architecture
// Created: 2002-08-25
// Author: Johan Persson (johanp@aditus.nu)
// Ver: $Id: dbschemaex1.php,v 1.1 2002/08/27 20:08:57
aditus Exp $
//
// License: This code is released under QPL
// Copyright (C) 2001,2002 Johan Persson
// Note: The actual drawing of the tables are
semi-automatically
// but you can easily adjust the individual tables
position
// with the 'tblposadj' array.
//
//========================================================================
*/
include
"../jpgraph.php";
include "../jpgraph_canvas.php";
include "../jpgraph_canvtools.php";
include
"../utils/misc/imgdbschema.inc";
include "../utils/jpdocgen/jpdb.php";
// Global callback to format the
table header names
function
FormatTblName(
$aName) {
// We want to replace any specifi
references to the
// 'JpGraph' project with the generic '<project>'
return
str_replace(
'JpGraph',
'<project>',
$aName);
}
// Global callback to format each
field name in the table
function
FormatFldName(
$aName,$aTable) {
return $aName
;
}
class Driver
{
var $ig
, $img, $iscale,
$ishape;
var $iymax
,$ixmax;
var $iwidth
,$iheight;
function Driver
() {
// Define Image size and
coordinate grid space to work within
$this
->iwidth = 600;
$this
->iheight= 750;
$this
->iymax = 50;
$this
->ixmax = 55;
// Setup a basic canvas
$this
->ig = new CanvasGraph(
$this->iwidth,$this
->iheight,'auto');
$this
->img = $this->
ig->img;
// Define the scale to be used
$this
->iscale = new CanvasScale(
$this->ig);
$this
->iscale->Set(
0,$this->ixmax
,0,$this->
iymax);
$this
->ishape = new Shape(
$this->ig,$this
->iscale);
// A small frame around the
canvas
$this
->ig->SetMargin(
2,3,2
,3);
$this
->ig->SetMarginColor(
"teal");
$this
->ig->InitFrame();
}
function Run
() {
$leftm
=1.5; // Left margin (for table schemes)
$topm
=5; // Top margin (for table schemes)
$tblwidth
=15; // Individual table width
$tlo
=1; // Offset for top line
// Add the background color for the project specific tables
$this
->ishape->IndentedRectangle($leftm,
$topm-1,3
*$tblwidth+$tlo+
6,45,
$tlo
+2*$tblwidth+
2,30,CORNER_BOTTOMLEFT,
'lightblue');
// Stroke the tables (series of
x,y offsets, If =-1 then use the
// automtic positioning
$tblposadj
=array($tlo,0,
$tblwidth+$tlo+2
,0,2*
$tblwidth+$tlo+4
,
0
,-1,16,-
1,16);
$dbschema
= new ImgDBSchema
('jpgraph_doc'
,'FormatTblName'
,'FormatFldName'
);
$dbschema
->SetMargin($leftm,
$topm);
$dbschema
->SetTableWidth
($tblwidth);
$dbschema
->Stroke($this->
img,$this->iscale
,$tblposadj);
$tt
= new CanvasRectangleText
();
$tt
->SetFillColor
('');
$tt
->SetColor('');
$tt
->SetFontColor
('navy');
// Add explanation
$tt
->SetFont(FF_ARIAL,
FS_NORMAL,12);
$tt
->Set('Project specific tables',$tblwidth+
$leftm+3,16
,15);
$tt
->Stroke($this->
img,$this->iscale
);
// Add title
$tt
->SetColor('');
$tt
->SetFont(FF_VERDANA,
FS_BOLD,26);
$tt
->Set('DDDA - DB Schema',9,
0.5,30);
$tt
->Stroke($this->
img,$this->iscale
);
// Add a version and date
$tt
->SetFillColor
('yellow');
$tt
->SetFont(FF_FONT1,
FS_NORMAL,10);
$tt
->Set("Generated: ".
date("ymd H:i",time
()),1,$this->
iymax*0.96,15
);
$tt
->Stroke($this->
img,$this->iscale
);
$this
->ig->Stroke();
}
}
$driver
= new Driver
();
$driver
->Run();
?>
Define, default value | Comment |
---|---|
"CACHE_DIR","/tmp/jpgraph_cache/" | The full absolute name of directory to be used as a cache. This directory must be readable and writable for PHP. Must end with '/' |
"TTF_DIR","/usr/local/fonts/ttf/" | Directory for JpGraph TTF fonts. Must end with '/' Note: The fonts must follow the naming conventions as used by the supplied TTF fonts in JpGraph. |
"USE_LIBRARY_GD2",false | Specify if we should use GD 2.x or GD 1.x If you have GD 2.x installed it is recommended that you use it since it will give a slightly, slightly better visual appearance for arcs. If you don't have GD2 installed this must be set to false! |
'USE_TRUECOLOR',true | Should the image be a truecolor image? Note 1: Can only be used with GD 2.0.2 and above. Note 2: GD 2.0.1 + PHP 4.0.6 on Win32 crashes when trying to use truecolor. Truecolor support is to be considered alpha since GD 2.x is still not considered stable (especially on Win32). Note 3: MUST be enabled to get background images working with GD2 Note 4: If enabled then truetype fonts will look very ugly => You can't have both background images and truetype fonts in the same image until these bugs has been fixed in GD 2.01 |
"USE_CACHE",false | Should the cache be used at all? By setting this to false no files will be generated in the cache directory. The difference from READ_CACHE being that setting READ_CACHE to false will still create the image in the cache directory just not use it. By setting USE_CACHE=false no files will even be generated in the cache directory. |
"READ_CACHE",true | Should we try to find an image in the cache before generating it? Set this define to false to bypass the reading of the cache and always regenerate the image. Note that even if reading the cache is disabled the cached will still be updated with the newly generated image. Set also "USE_CACHE" below. |
"DEFAULT_GFORMAT","auto" | Default graphic format set to "auto" which will automatically choose the best available format in the order png,gif,jpg (The supported format depends on what your PHP installation supports) |
"USE_IMAGE_ERROR_HANDLER",true | Determine if the error handler should be image based or purely text based. Image based makes it easier since the script will always return an image even in case of errors. |
"USE_APPROX_COLORS",true | If the color palette is full should JpGraph try to allocate the closest match? If you plan on using background image or gradient fills it might be a good idea to enable this. If not you will otherwise get an error saying that the color palette is exhausted. The drawback of using approximations is that the colors might not be exactly what you specified. Note1: This does only apply to a palette image, not true color images since they don't have the limitations of maximum number of colors. |
"LANGUAGE_CYRILLIC",false | Special unicode language support |
"ERR_DEPRECATED",false | Should usage of deprecated functions and parameters give a fatal error? (Useful to check if code is future proof.) |
"BRAND_TIMING",false | Should the time taken to generate each picture be branded to the lower left in corner in each generated image? Useful for performance measurements generating graphs |
"BRAND_TIME_FORMAT","Generated in: %01.3fs" | What format should be used for the timing string? |
The following defines should very rarely need to be changed
Define, default value | Comment |
---|---|
"CACHE_FILE_GROUP","wwwadmin" | What group should the cached file belong to (Set to "" will give the default group for the "PHP-user") Please note that the Apache user must be a member of the specified group since otherwise it is impossible for Apache to set the specified group. |
"CACHE_FILE_MOD",0664 | What permissions should the cached file have (Set to "" will give the default permissions for the "PHP-user") |
"USE_BRESENHAM",false | Decide if we should use the Bresenham circle algorithm or the built in Arc(). Bresenham gives better visual appearance of circles but is more CPU intensive and slower then the built in Arc() function in GD. Turned off by default for speed |
"JPG_DEBUG",false | Enable some extra internal debug information to be shown. (Should only be changed if your first name is Johan and you happen to know what you are doing. You have been warned.) |
"_CSIM_SPECIALFILE","_csim_special_" | Special file name to indicate that we only want to calc the image map in the call to Graph::Stroke() used internally from the GetHTMLCSIM() method. |
"_CSIM_DISPLAY","_jpg_csimd" | HTTP GET argument that is used with image map to indicate to the script to just generate the image and not the full CSIM HTML page. |