This section describes the use of the data_points
callback to generate an HTML image map (or other similar construct) from
plot data.
An image map created using this callback will contain links from the
data points or shapes on the plot.
This feature was first added in PHPlot-5.7.0 as an experimental feature,
and was first documented in this Reference Manual with PHPlot-6.0.0.
Use of callbacks is documented in Section 4.4, “Callbacks”.
The data_points
callback makes the
device coordinates of
plotted data available to a script using PHPlot.
If a script registers a function as a handler for the
data_points
callback name, the function will be called
repeatedly when the plot is being generated. Each call will contain
parameters describing the graphics for the corresponding data point.
These parameters can be used to create an HTML image map.
This feature is most likely only useful when generating embedded image data with PHPlot. (See EncodeImage for details on embedded image data.) This is because HTML requires the image map be included in the HTML page which contains the reference to the plot image. The browser will first request the HTML page, then make a second request for the image. Normally, the image is generated by a script using PHPlot, but the image map has to be available before this script runs. Using embedded image data allows a single PHP script to produce both the image map and the image data, and return the result as a single page.
Nevertheless, it is also possible to create an image map with a non-embedded image. See Section 4.10.4, “Image Maps with Non-embedded Image Data” for details.
The data_points
callback works with the following plot
types:
bars and stackedbars (both horizontal and vertical)
ohlc, candlesticks, and candlesticks2
points and linepoints (both standard and error bar plots)
No other plot type is supported. This includes
lines
,
squared
, and
thinbarline
,
which do not have well-defined areas which could map to data points, and
area
,
squaredarea
,
stackedarea
, and
stackedsquaredarea
for which this feature has not been implemented.
The rest of this section contains details on the callback, usage with each plot type, and additional information.
To register a callback function to handle data_points
, use:
$plot->SetCallback('data_points', 'my_handler', $my_arg);
Where my_handler
is the name of your function,
$my_arg
is an optional additional argument to pass
to your function.
The data_points
callback function
(my_handler()
above) will be called with 5
fixed-purpose arguments followed by variable arguments. The number and
purpose of the variable arguments depends on the plot type. If your
handler only needs to work with one specific plot type, you can declare
these arguments in your function definition.
If your handler must handle multiple plot types, define your function without
arguments and use func_get_arg()
or
func_get_args()
to access the arguments.
You can use the value of the 3rd argument, $shape
,
to determine the number and usage of the variable arguments, since there is
one specific function argument set for each value of $shape
.
See Section 4.10.2, “Image Maps - data_points Callback Parameter Summary” for more information.
Here are the fixed arguments to the data_points
callback function, with this general declaration:
function my_handler($img, $passthru, $shape, $row, $column, ...)
The image resource (standard for all callbacks).
Not generally used with a data_points
callback, which
cannot safely draw on the image (since PHPlot is in the middle of drawing
the plot on the same image).
Pass-through argument, supplied in the SetCallback() call
(standard for all callbacks, referred to above as $my_arg
).
You can use this however you want, or ignore it.
A word describing the shape of the area being described. This does not necessarily correspond to an HTML image map <area> shape. Each plot type passes a specific shape value, and the shape value defines the usage of the variable arguments.
The number of the data row being plotted. This typically corresponds to the ordinal of the X axis values (Y for horizontal plots), starting with 0 for the first point, 1 for the second point, etc.
The column, or data set index, starting with 0 for the first data set. This indicates which Y value for a given X, for example, or which bar within a bar group, or segment within a stacked bar. (For horizontal plots, this would indicate which X for a given Y.) Always 0 for pie charts and OHLC plots, which only have a single data set.
For the variable arguments, refer to the sections below which describe each plot type.
With plot types bars and stackedbars, an image map can be produced which indicates the area of each bar or stacked bar segment. This works with both vertical and horizontal plots.
For bar and stackedbar plots, the data_points
callback
has this form:
function my_handler($img, $passthru, $shape, $row, $column, $x1, $y1, $x2, $y2)
The first 2 arguments are standard for all PHPlot callbacks and are not described here. The next 3 arguments are common to all data_points callbacks, and there are 4 additional arguments:
Always rect
, indicating a rectangle shape.
This is the bar group index. The left-most bar group (for vertical bar charts) is row 0.
This is the bar index within a group. For vertical plot type 'bars', index 0 is the left-most in the group. For vertical plot type 'stackedbars', index 0 is the bar segment closest to the X axis.
Device coordinates of the upper left corner of a bar or segment.
Device coordinates of the lower right corner of a bar or segment.
Generating an image map for bar and stackedbar plots is straight-forward.
The provided $shape
and coordinates are compatible with
HTML <area> markup.
You must provide the URL, alternate text, and optionally a title (tooltip text).
This example appends the image map line to a string. sprintf() is used to convert the coordinates to integers for cleaner HTML.
$coords = sprintf("%d,%d,%d,%d", $x1, $y1, $x2, $y2); $image_map .= " <area shape=\"rect\" coords=\"$coords\"" .. " title=\"$title_text\" alt=\"$alt_text\" href=\"$url\">\n";
The $url
, $title_text
, and
$alt_text
would typically depend on the passed
$row
and $column
.
Refer to Section 5.44, “Example - Image Map from Bar Chart” for a complete example of an image map for a bar chart.
With plot type boxes, an image map can be produced which indicates the area of each data point. This area is the bounding box which includes the box and both whiskers. The bounding box does not include any outliers.
For box plots, the data_points
callback
has this form:
function my_handler($img, $passthru, $shape, $row, $column, $x1, $y1, $x2, $y2)
The first 2 arguments are standard for all PHPlot callbacks and are not described here. The next 3 arguments are common to all data_points callbacks, and there are 4 additional arguments:
Always rect
, indicating a rectangle shape.
The index of the data row, starting with 0 for the first X value.
This is unused, and always 0.
Device coordinates of the upper left corner.
Device coordinates of the lower right corner.
The upper left and lower right coordinates above refer to the bounding box as described above.
Generating an image map for box plots is straight-forward.
The provided $shape
and coordinates are compatible with
HTML <area> markup.
You must provide the URL, alternate text, and optionally a title (tooltip text).
This example appends the image map line to a string. sprintf() is used to convert the coordinates to integers for cleaner HTML.
$coords = sprintf("%d,%d,%d,%d", $x1, $y1, $x2, $y2); $image_map .= " <area shape=\"rect\" coords=\"$coords\"" .. " title=\"$title_text\" alt=\"$alt_text\" href=\"$url\">\n";
The $url
, $title_text
, and
$alt_text
would typically depend on the passed
$row
.
Section 5.44, “Example - Image Map from Bar Chart” contains a complete example of an image map for a bar chart, and the parameters and usage for box plots are the same except that the $col (column) parameter is always 0, since there is only one data set.
With plot type bubbles, an image map can be produced which indicates the area of each bubble.
For bubbles plots, the data_points
callback
has this form:
function my_handler($img, $passthru, $shape, $row, $column, $x, $y, $diam)
The first 2 arguments are standard for all PHPlot callbacks and are not described here. The next 3 arguments are common to all data_points callbacks, and there are 3 additional arguments:
Always circle
, indicating a disk shape.
The row is the index for the independent variable X. The first X value has index 0.
The column is the index for the dependent variable Y. For the first (or only) dataset for each X, the column index is 0.
Device coordinates of the center of the bubble.
Diameter of the bubble, in pixels.
Generating an image map for bubble plots is straight-forward. PHPlot provides parameters that are compatible with HTML image map markup, except that PHPlot provides a diameter, and HTML requires the radius.
Here is an example of generating one area in an image map from a bubbles plot. You must provide the URL, alternate text, and optionally a title (tooltip text). This appends the image map line to a string. sprintf() is used to convert the coordinates to integers for cleaner HTML.
$coords = sprintf("%d,%d,%d", $x, $y, $diam / 2); $image_map .= " <area shape=\"circle\" coords=\"$coords\"" . " title=\"$title_text\" alt=\"$alt_text\" href=\"$url\">\n";
The $url
, $title_text
, and
$alt_text
would typically depend on the passed
$row
and $column
.
Other than the above code, a script to generate an image map for a bubbles plot would be similar to Section 5.44, “Example - Image Map from Bar Chart”, which produces a bar chart.
With plot types ohlc, candlesticks, and candlesticks2 (collectively called OHLC - open, high, low, close plots), an image map can be produced which indicates the area of each data point. For candlesticks and candlesticks2 plots, this area is the bounding box containing the candlestick and its wicks. For ohlc plots, this area is the bounding box formed by the vertical line and horizontal ticks.
For OHLC plots, the data_points
callback
has this form:
function my_handler($img, $passthru, $shape, $row, $column, $x1, $y1, $x2, $y2)
The first 2 arguments are standard for all PHPlot callbacks and are not described here. The next 3 arguments are common to all data_points callbacks, and there are 4 additional arguments:
Always rect
, indicating a rectangle shape.
The index of the data row, starting with 0 for the first X value.
This is unused, and always 0.
Device coordinates of the upper left corner.
Device coordinates of the lower right corner.
The upper left and lower right coordinates above refer to the bounding box as described above.
Generating an image map for OHLC plots is straight-forward.
The provided $shape
and coordinates are compatible with
HTML <area> markup.
You must provide the URL, alternate text, and optionally a title (tooltip text).
This example appends the image map line to a string. sprintf() is used to convert the coordinates to integers for cleaner HTML.
$coords = sprintf("%d,%d,%d,%d", $x1, $y1, $x2, $y2); $image_map .= " <area shape=\"rect\" coords=\"$coords\"" .. " title=\"$title_text\" alt=\"$alt_text\" href=\"$url\">\n";
The $url
, $title_text
, and
$alt_text
would typically depend on the passed
$row
.
Section 5.44, “Example - Image Map from Bar Chart” contains a complete example of an image map for a bar chart, and the parameters and usage for OHLC plots are the same except that the $col (column) parameter is always 0, since there is only one data set.
With plot type pie, an image map can be produced which indicates the area of each pie segment. However, PHPlot only supplies the values which identify the outline of the pie segment, and HTML maps do not support areas of this shape. Therefore, the callback handler function needs to generate one or more polygons which approximate the pie segment area.
PHPlot does not attempt to draw pie segments that are too small (due to the implementation of the PHP/GD drawing function). If a segment's calculated start angle and end angle are equal (after converting to integers), the segment will not be drawn, and the data_points callback will not be called for that segment.
For pie charts, the data_points
callback has this form:
function my_handler($img, $passthru, $shape, $row, $column, $x, $y, $pie_width, $pie_height, $start_angle, $end_angle)
The first 2 arguments are standard for all PHPlot callbacks and are not described here. The next 3 arguments are common to all data_points callbacks, and there are 6 additional arguments:
Always pie
, indicating a pie segment of an ellipse.
The pie segment index, starting at 0 for the first segment. (By default, segments are drawn counter-clockwise from 0 degrees, but this can be changed.)
This is unused, and always 0.
Device coordinates of the center of the pie.
Horizontal diameter of the pie, in pixels.
Vertical diameter of the pie, in pixels.
Starting angle for the segment, in clockwise degrees (see note).
Ending angle for the segment, in clockwise degrees.
clockwise degrees means (360 - A), where A is an angle measured in the conventional sense: counter-clockwise from the X axis. For example, a pie segment that starts at the top of the pie ('North') and ends at the bottom point ('South') would have start_angle=270 and end_angle=90. The start_angle is always greater than the end angle.
Generating an image map for pie charts is more involved than with other plot types. Each pie segment is defined by the ellipse center point, the two diameter values, and the start and end angles. Due to the PHP/GD implementation, PHPlot uses clockwise angles (360-A), so the start_angle is greater than the end_angle, and the segment is drawn clockwise from the end_angle to the start_angle.
HTML image maps do not support ellipse section shapes directly. Therefore, the callback function has to approximate the area using one or more polygons.
The method shown in the example linked below approximates the pie segment area using a polygon with one point at the pie center, one point at each end of the arc, and zero or more points along the arc , such that the maximum separation of points along the circumference is no more than 20 degrees. This has been found to produce a good fit for image maps. More details on the method can be found in the example.
Once you have your points (converted to integers, in an array
$points
with X and Y values alternating), you can generate
a line in the image map as follows.
This example appends the image map line to a string.
$coords = implode(',', $points); $image_map .= " <area shape=\"poly\" coords=\"$coords\"" . " title=\"$title_text\" alt=\"$alt_text\" href=\"$url\">\n";
The $url
, $title_text
, and
$alt_text
would typically depend on the passed
$row
.
Refer to Section 5.45, “Example - Image Map from Pie Chart” for a complete example of an image map for a pie chart.
With plot types points and linepoints, an image map can be produced which indicates the area around each point. The lines in a linepoints plot are not part of the image map areas. This also works with error plots that use these plot types, however the error bars are not part of the image map areas.
For points and linepoints plots, the data_points
callback
has this form:
function my_handler($img, $passthru, $shape, $row, $column, $x, $y)
The first 2 arguments are standard for all PHPlot callbacks and are not described here. The next 3 arguments are common to all data_points callbacks, and there are 2 additional arguments:
Always dot
, indicating a single point.
The row is the index for the independent variable X. The first X value has index 0.
The column is the index for the dependent variable Y. For the first (or only) dataset for each X, the column index is 0.
Device coordinates of the center of the point marker.
Generating an image map for points and linepoints plots is straight-forward. PHPlot provides only the center coordinates for each point marker. It does not indicate the shape or size of the marker, nor the coordinates of any line segments or error bars. To generate an image map, you should use a fixed radius size and define the image map areas as circles with that radius centered around each data point. You need to choose a radius. A larger radius provides a larger clickable area, but the area of adjacent points may overlap.
Here is an example of generating one area in an image map from a points or linepoints plot. You must provide the URL, alternate text, and optionally a title (tooltip text). This appends the image map line to a string. sprintf() is used to convert the coordinates to integers for cleaner HTML. This example uses a 20 pixel radius for the areas around each data point.
define('MAP_RADIUS', 20); // Capture area circle radii $coords = sprintf("%d,%d,%d", $x, $y, MAP_RADIUS); $image_map .= " <area shape=\"circle\" coords=\"$coords\"" . " title=\"$title_text\" alt=\"$alt_text\" href=\"$url\">\n";
The $url
, $title_text
, and
$alt_text
would typically depend on the passed
$row
and $column
.
Other than the above code, a script to generate an image map for a points or linepoints plot would be similar to Section 5.44, “Example - Image Map from Bar Chart”, which produces a bar chart.
The following table contains a summary of the data_points
callback parameters for each supported plot type.
Plot Type(s) | Callback Parameters / Notes |
---|---|
bars, stackedbars | $img, $passthru, $shape='rect', $row, $column, $x1, $y1, $x2, $y2 |
Image map area does not include shading. | |
boxes | $img, $passthru, $shape='rect', $row, 0, $x1, $y1, $x2, $y2 |
Rectangle shape includes box and whiskers. It does not include any outliers. | |
bubbles | $img, $passthru, $shape='circle', $row, $column, $x, $y, $diam |
x,y is center. Use diam/2 for radius in image map circle area. | |
candlesticks, candlesticks, ohlc | $img, $passthru, $shape='rect', $row, 0, $x1, $y1, $x2, $y2 |
Rectangle shape includes body, wicks, ticks of each candlestick or OHLC marker. | |
pie | $img, $passthru, $shape='pie', $row, 0, $x, $y, $width, $height, $start_angle, $end_angle |
Callback needs to fit a polygon to the ellipse segment. | |
points, linepoints | $img, $passthru, $shape='dot', $row, $column, $x, $y |
x,y is center. Supply a radius for image map circle areas. Image map area will cover the points only, not lines. |
Since most PHPlot scripts will not produce image maps, the burden of converting data points into a format for HTML image maps was left to the implementation in the callback function. This is why PHPlot passes the diameter values it already calculated (instead of radius values), and why pie chart segments must be interpolated by the callback function.
You can generate image maps for error plots (data types data-data-error and data-data-yx-error) with points and linepoints plot types, but the image map areas will not include the error bars. For these plot types, the only the coordinates of the data points are provided.
PHPlot does not provide the data values from the data array that go with
the points. If you need these values, for example in tooltips, your callback
function needs to get them from the data array, using the $row and $column
index values. This may be complex for pie charts (for example, if you want
tooltip text to show the percentage value of the pie segment).
Section 5.45, “Example - Image Map from Pie Chart” shows access to data values for a pie
chart in the simple case of data type text-data-single
.
Section 5.46, “Example - Image Map and Non-embedded Plot Image” shows access to data values for a
bar chart.
For OHLC plots (candlesticks, candlesticks2, and ohlc plot types), and for box plots, PHPlot does not provide the callback with the coordinates of individual features (such as the candlestick body rather than the high point wick). PHPlot only provides the bounding box rectangle for the overall data point graphic.
The image map must be located in the same HTML file as the image reference.
Although the HTML definition of the usemap
attribute
of the <img>
tag seems to indicate that a URL to an
external file containing the map may be used, this does not in fact work.
It is also possible to generate an image map when the PHPlot script produces an image in the normal way (not embedded) and returns it to the browser as image data. But the script will need to run twice: once to generate the PHPlot image, and once to generate the containing HTML page with the image map. (You can use two separate scripts instead, but this is not recommended, since both operations must create identical plots so the image map areas correspond to the plot areas.)
In the following example, the script normally generates an HTML page. The page
contains an image map, generated with PHPlot, and also a
<img>
image tag which points back to the same script
to have it generate the plot image.
When requesting the image, the script adds a parameter 'mode=plot' to the
URL. This tells the second execution of the script to generate the image
data instead of the HTML page.
The obvious drawback to this method is that you are processing a complete plot twice each time a plot is needed. The first time, only the image map is needed, and the plot itself is discarded. This is inefficient, especially if the plotting script needs to query a database or perform extensive calculations.
Another concern is if the script queries a database, the data could change between the two uses of the script, resulting in an image map and plot which do not correlate.
The rest of this section contains selected, annotated code from Section 5.46, “Example - Image Map and Non-embedded Plot Image”.
Start by checking for the mode parameter:
# Produce an image if the URL has mode=plot, and an HTML page otherwise: $do_html = empty($_GET['mode']) || $_GET['mode'] != 'plot';
The callback handler is the same as the other imagemap examples, in that it appends to the global string $image_map one line from the image map.
# Callback for 'data_points' : Generate 1 line in the image map. function store_map($im, $data, $shape, $row, $col, $x1, $y1, $x2, $y2) { ... }
The generate_html()
function creates the containing
HTML page. Only parts of the code are shown.
function generate_html() { global $image_map;
Create a self-referencing URL with mode=plot parameter for the
<img>
tag:
# If the URL already has parameters, use & separator, else ?. $sep = empty($_SERVER['QUERY_STRING']) ? '?' : '&'; $url = htmlspecialchars($_SERVER['REQUEST_URI'] . $sep . 'mode=plot');
Now generate the HTML page. Include the image map using the global string
$image_map
, which our callback function has
built line-by-line as PHPlot produced the plot.
Also include the reference to the plot image. This will result in the browser
making a second request to the script, this time with the mode=plot parameter.
echo <<<END <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> ... <map name="map1"> $image_map </map> ... <img src="$url" alt="Plot image" usemap="#map1"> ... </html> END; }
This ends the generate_html()
function.
In the main body of the script, create a PHPlot object and configure the
plot as usual. Set the data_points
callback. (You need only
do this in the case of generating HTML, not the image case.)
There are two other places where the operation differs for the HTML or image
generation, based on the $do_html
flag: disabling automatic
output with SetPrintImage, and calling
the generate_html()
function at the end.
$plot = new PHPlot(800, 600); if ($do_html) { // Do not output the image in this mode: $plot->SetPrintImage(False); // Set the callback for image map generation: $plot->SetCallback('data_points', 'store_map'); } ... // Set up the plot, data values, plot type, etc. // Output the image (in plot mode), or build the image map (in html mode): $plot->DrawGraph(); if ($do_html) generate_html();
That's all. If $do_html
is true, no image will be produced
(due to SetPrintImage(False)
),
and generate_html()
will be called.
If $do_html
is false, DrawGraph()
will output the plot image, and the map data will be not be produced or output.
This version of the manual was produced for the
PHPlot Sourceforge project web service site, which requires the logo on each
page.
To download a logo-free copy of the manual, see the
PHPlot project downloads
area.