98 |
- |
1 |
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
|
|
|
2 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /><title>5.45. Example - Image Map from Pie Chart</title><link rel="stylesheet" type="text/css" href="phplotdoc.css" /><meta name="generator" content="DocBook XSL Stylesheets V1.78.1" /><link rel="home" href="index.html" title="PHPlot Reference Manual" /><link rel="up" href="examples.html" title="Chapter 5. PHPlot Examples" /><link rel="prev" href="ex-imagemap-bars.html" title="5.44. Example - Image Map from Bar Chart" /><link rel="next" href="ex-imagemap-nonembed.html" title="5.46. Example - Image Map and Non-embedded Plot Image" /></head><body><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">5.45. Example - Image Map from Pie Chart</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ex-imagemap-bars.html">Prev</a> </td><th width="60%" align="center">Chapter 5. PHPlot Examples</th><td width="20%" align="right"> <a accesskey="n" href="ex-imagemap-nonembed.html">Next</a></td></tr></table><hr /></div><div class="sect1"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="ex-imagemap-pie"></a>5.45. Example - Image Map from Pie Chart</h2></div></div></div><p>
|
|
|
3 |
This example produces an HTML page with an embedded image containing a pie
|
|
|
4 |
chart, and an image map. The image map makes the pie sectors in the chart
|
|
|
5 |
into hotlinks. In this example, tool-tip text identifies the segment
|
|
|
6 |
number and its numeric value, and clicking on a pie segment displays the
|
|
|
7 |
same text in an alert popup. These looks could be used instead to link to
|
|
|
8 |
another web page, display data in a popup window, etc.
|
|
|
9 |
</p><p>
|
|
|
10 |
This example also shows getting access to the data values. The
|
|
|
11 |
callback handler accesses the data array to get the current segment value
|
|
|
12 |
and uses that in the tool-tip text and alert box. This is dependent on the
|
|
|
13 |
data type of the array, and the code shown here only works with data type
|
|
|
14 |
text-data-single.
|
|
|
15 |
</p><p>
|
|
|
16 |
Unlike the <a class="link" href="ex-imagemap-bars.html" title="5.44. Example - Image Map from Bar Chart">previous example</a> with a
|
|
|
17 |
bar chart, in this example the callback function needs to do some more
|
|
|
18 |
significant calculations in order to produce the image map areas. This is
|
|
|
19 |
because HTML image maps do not directly support any area shape which
|
|
|
20 |
corresponds to a pie chart segment.
|
|
|
21 |
Therefore the callback function approximates each pie chart segment with a
|
|
|
22 |
polygon. This is explained in the code shown below.
|
|
|
23 |
</p><p>
|
|
|
24 |
See <a class="xref" href="adv-imgmap.html" title="4.10. Image Maps for Plot Data">Section 4.10, “Image Maps for Plot Data”</a> for more information on image maps.
|
|
|
25 |
This capability was added in PHPlot-5.7.0.
|
|
|
26 |
See <a class="xref" href="EncodeImage.html" title="EncodeImage"><span class="refentrytitle">EncodeImage</span></a> for more on embedding plot images within
|
|
|
27 |
an HTML page.
|
|
|
28 |
</p><div class="example"><a id="example-imagemap-pie"></a><p class="title"><strong>Example 5.45. Image Map from Pie Chart (Browser screenshot)</strong></p><div class="example-contents"><div class="informalfigure"><div class="mediaobject"><img src="images/imagemap-pie.png" alt="Image Map from Pie Chart Example" /></div></div><pre class="programlisting"><?php
|
|
|
29 |
# PHPlot example: Pie chart, embedded image with image map
|
|
|
30 |
require_once 'phplot.php';
|
|
|
31 |
|
|
|
32 |
# This global string accumulates the image map AREA tags.
|
|
|
33 |
$image_map = "";
|
|
|
34 |
|
|
|
35 |
# Data for pie chart:
|
|
|
36 |
$data = array(
|
|
|
37 |
array('', 20),
|
|
|
38 |
array('', 30),
|
|
|
39 |
array('', 10),
|
|
|
40 |
array('', 40),
|
|
|
41 |
array('', 10),
|
|
|
42 |
);
|
|
|
43 |
|
|
|
44 |
/*
|
|
|
45 |
Callback handler for generating an image map for a pie chart.
|
|
|
46 |
|
|
|
47 |
NOTE: The code in this function is excluded from the license terms for
|
|
|
48 |
PHPlot, the PHPlot Reference Manual, and the PHPlot Test Suite. You may
|
|
|
49 |
freely copy, use, modify, and redistribute the code in this function.
|
|
|
50 |
Attribution is not necessary. Or, to put it another way, I am placing
|
|
|
51 |
this function in the public domain.
|
|
|
52 |
|
|
|
53 |
Arguments:
|
|
|
54 |
$im, $passthru : standard arguments for all callbacks.
|
|
|
55 |
$shape : always 'pie'
|
|
|
56 |
$segment : 0 for the first pie segment, 1 for the next, etc.
|
|
|
57 |
$xc, $yc : Center of the pie, in device coordinates
|
|
|
58 |
$wd, $ht : Pie diameters - width (horizontal), height (vertical)
|
|
|
59 |
$start_angle, $end_angle : Segment arc angles, in degrees, offset from
|
|
|
60 |
360. That is, the values are (360-A) for angle A. This is the way
|
|
|
61 |
PHPlot processes the angles for the GD function imagefilledarc().
|
|
|
62 |
Note that sin(360-A) = -sin(A); and cos(360-A) = cos(A).
|
|
|
63 |
Since the Y axis (sin) is reversed in device, or image, coordinates
|
|
|
64 |
with Y=0 at the top, this works out correctly.
|
|
|
65 |
|
|
|
66 |
Method used:
|
|
|
67 |
Approximate a pie segment using a polygon. Note the pie is not necessarily
|
|
|
68 |
circular, but is an ellipse.
|
|
|
69 |
+ The 1st point is the pie center.
|
|
|
70 |
+ The 2nd point is on the circumference*, at the start angle.
|
|
|
71 |
+ The last point is on the circumference*, at the end angle.
|
|
|
72 |
+ In between the 2nd and last point are N>=0 additional points on the
|
|
|
73 |
circumference*, spaced no more than 20 degrees apart. (20 is chosen by
|
|
|
74 |
trial and error for a reasonable fit.) So small segments will be approximated
|
|
|
75 |
by a single triangle. Larger segments will have more vertices.
|
|
|
76 |
|
|
|
77 |
*Note: These points are actually slightly outside the circumference.
|
|
|
78 |
This is done by increasing the two radius values by a small amount (2 pixels).
|
|
|
79 |
This produces a better fit, for the case where we want to make sure all the
|
|
|
80 |
interior is covered, even if some of the exterior is also included. (Using
|
|
|
81 |
the actual radii would result in the area omitting a small part of the pie
|
|
|
82 |
interior. For an image map, this would result in dead spaces.)
|
|
|
83 |
|
|
|
84 |
The segment subdivisions are made to have about equal angles. This results
|
|
|
85 |
in a closer fit. For example, with a maximum sub-segment arc of 20 degrees,
|
|
|
86 |
and a segment of 24 degrees, we make two 12 degree sub-segments rather than a
|
|
|
87 |
20 degree and a 4 degree.
|
|
|
88 |
|
|
|
89 |
Note: Web image map coordinates have 0,0 in upper left, so Y is reversed.
|
|
|
90 |
|
|
|
91 |
The pass-through argument gets the data array. This is used to include the
|
|
|
92 |
pie segment value in the URL and/or tooltip. This will only work with data
|
|
|
93 |
type text-data-single, where array values map 1:1 to segment values.
|
|
|
94 |
*/
|
|
|
95 |
function store_map($im, $data, $shape, $segment, $unused,
|
|
|
96 |
$xc, $yc, $wd, $ht, $start_angle, $end_angle)
|
|
|
97 |
{
|
|
|
98 |
global $image_map;
|
|
|
99 |
|
|
|
100 |
# Choose the largest step_angle <= 20 degrees that divides the segment
|
|
|
101 |
# into equal parts. (20 degrees is chosen as a threshold.)
|
|
|
102 |
# Note start_angle > end_angle due to reversal (360-A) of arguments.
|
|
|
103 |
$arc_angle = $start_angle - $end_angle;
|
|
|
104 |
$n_steps = (int)ceil($arc_angle / 20);
|
|
|
105 |
$step_angle = $arc_angle / $n_steps;
|
|
|
106 |
|
|
|
107 |
# Radius along horizontal and vertical, plus a tiny adjustment factor.
|
|
|
108 |
$rx = $wd / 2 + 2;
|
|
|
109 |
$ry = $ht / 2 + 2;
|
|
|
110 |
# Push the initial point into the array: the center of the pie.
|
|
|
111 |
$points = array($xc, $yc);
|
|
|
112 |
|
|
|
113 |
# Loop by step_angle from end_angle to start_angle.
|
|
|
114 |
# Don't use "$theta += $step_angle" because of cumulative error.
|
|
|
115 |
# Note $theta and $done_angle are in radians; $step_angle and $end_angle
|
|
|
116 |
# are in degrees.
|
|
|
117 |
$done_angle = deg2rad($start_angle);
|
|
|
118 |
|
|
|
119 |
for ($i = 0; ; $i++) {
|
|
|
120 |
# Advance to next step, but not past the end:
|
|
|
121 |
$theta = min($done_angle, deg2rad($end_angle + $i * $step_angle));
|
|
|
122 |
|
|
|
123 |
# Generate a point at the current angle:
|
|
|
124 |
$points[] = (int)($xc + $rx * cos($theta));
|
|
|
125 |
$points[] = (int)($yc + $ry * sin($theta));
|
|
|
126 |
|
|
|
127 |
# All done after generating a point at done_angle.
|
|
|
128 |
if ($theta >= $done_angle) break;
|
|
|
129 |
}
|
|
|
130 |
|
|
|
131 |
# Demonstration data: Title (and tool-tip text), alt text, URL:
|
|
|
132 |
# Fetch segment value from data arrayL
|
|
|
133 |
$value = $data[$segment][1];
|
|
|
134 |
$title = "Segment $segment = $value";
|
|
|
135 |
$alt = "Region for segment $segment";
|
|
|
136 |
$href = "javascript:alert('Segment $segment = $value')";
|
|
|
137 |
$coords = implode(',', $points);
|
|
|
138 |
|
|
|
139 |
# Generate the image map area:
|
|
|
140 |
$image_map .= " <area shape=\"poly\" coords=\"$coords\""
|
|
|
141 |
. " title=\"$title\" alt=\"$alt\" href=\"$href\">\n";
|
|
|
142 |
}
|
|
|
143 |
|
|
|
144 |
# Create and configure the PHPlot object.
|
|
|
145 |
$plot = new PHPlot(640, 480);
|
|
|
146 |
# Disable error images, since this script produces HTML:
|
|
|
147 |
$plot->SetFailureImage(False);
|
|
|
148 |
# Disable automatic output of the image by DrawGraph():
|
|
|
149 |
$plot->SetPrintImage(False);
|
|
|
150 |
# Set up the rest of the plot:
|
|
|
151 |
$plot->SetTitle("PHPlot Example: Pie Chart with Image Map");
|
|
|
152 |
$plot->SetImageBorderType('plain');
|
|
|
153 |
$plot->SetDataValues($data);
|
|
|
154 |
$plot->SetDataType('text-data-single');
|
|
|
155 |
$plot->SetPlotType('pie');
|
|
|
156 |
# Set the data_points callback which will generate the image map.
|
|
|
157 |
# Include the data array as the pass-through argument, for tooltip text:
|
|
|
158 |
$plot->SetCallback('data_points', 'store_map', $data);
|
|
|
159 |
# Produce the graph; this also creates the image map via callback:
|
|
|
160 |
$plot->DrawGraph();
|
|
|
161 |
|
|
|
162 |
# Now output the HTML page, with image map and embedded image:
|
|
|
163 |
?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
|
|
164 |
"http://www.w3.org/TR/html4/loose.dtd">
|
|
|
165 |
<html>
|
|
|
166 |
<head>
|
|
|
167 |
<title>PHPlot Example: Pie Chart with Image Map</title>
|
|
|
168 |
</head>
|
|
|
169 |
<body>
|
|
|
170 |
<h1>PHPlot Example: Pie Chart with Image Map</h1>
|
|
|
171 |
<map name="map1">
|
|
|
172 |
<?php echo $image_map; ?>
|
|
|
173 |
</map>
|
|
|
174 |
<p>This is a plot with image map and tooltip text.</p>
|
|
|
175 |
<img src="<?php echo $plot->EncodeImage();?>" alt="Plot Image" usemap="#map1">
|
|
|
176 |
</body>
|
|
|
177 |
</html>
|
|
|
178 |
</pre></div></div><br class="example-break" /></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ex-imagemap-bars.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="examples.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ex-imagemap-nonembed.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">5.44. Example - Image Map from Bar Chart </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 5.46. Example - Image Map and Non-embedded Plot Image</td></tr></table></div></body></html>
|