5 class PieChart
extends Chart
{
7 protected $legend_precision = 1; // percentage round
9 protected $spacing = 2; // spacing between slices
12 public function __construct($width=NULL, $height=NULL)
16 parent
::__construct($width, $height);
18 $this->set_margins(0);
20 $this->colors
['colors'] = array( // for drawing "value lines"
21 array('#f8d01b', NULL, NULL),
22 array('#f1b71e', NULL, NULL),
23 array('#e38a23', NULL, NULL),
24 array('#d65728', NULL, NULL),
25 array('#ca1d2f', NULL, NULL),
26 array('#c8004d', NULL, NULL),
27 array('#db006f', NULL, NULL),
28 array('#ef008f', NULL, NULL),
29 array('#f7009a', NULL, NULL)
31 $this->colors
['legend_color'] = array('#fefefe', NULL, NULL); // background legend color
34 public function set_legend_precision($value)
36 $this->legend_precision
= (int) $value;
39 public function draw()
43 foreach ($this->values
as $i => $value)
45 $this->values
[$i] = 0;
47 $plot_sizes = $this->get_plot_area(); // size of the graph area
48 $max_diameter = $plot_sizes[1]; // height of the plot area
50 // get size of the percentage legend
51 $t = '100'. ($this->legend_precision ?
'.'. str_repeat('0', $this->legend_precision
) : '');
52 $box_points = imagettfbbox($this->font_size
, 0, $this->font
, $t);
53 $legend_slice_width = $box_points[4]-$box_points[6];
54 $legend_slice_height = $box_points[3]-$box_points[5];
56 $width = $max_diameter-$this->spacing
;
57 $height = $max_diameter*0.6;
58 $height_3d = $max_diameter*0.1;
60 $this->legend
= array_keys($this->values
); // set legend
62 // try to determine width of the legend box (exact width depends on relative font size which could be set when calling $this->draw_legend and margins)
64 foreach ($this->legend
as $l)
66 $box_points = imagettfbbox($this->font_size
, 0, $this->font
, $l);
67 $legend_width = $box_points[4]-$box_points[6];
68 if ($legend_width < $width)
69 $legend_width = $width;
72 $legend_width +
= 0; // some margins
74 $margin_left = ($this->width
-$width+
35) / 2;
75 $center_x = $width/2+
$margin_left;
76 $center_y = $this->margin_top +
($height+
$height_3d)/2;
78 $ratio = array_sum($this->values
)/360;
80 if ($ratio != 0) // so there is something to display
83 // steps for gradient in 3d
90 foreach ($this->values
as $key => $value)
92 // make the color for 3d darker
93 $hexcolor = $this->get_color('colors', $i, 0);
94 if( $hexcolor !== false ) {
95 $colortop = utilities
::hex2rgb($hexcolor);
96 $colorbottom[0] = $colortop[0]-40 < 0 ?
0 : $colortop[0]-40;
97 $colorbottom[1] = $colortop[1]-40 < 0 ?
0 : $colortop[1]-40;
98 $colorbottom[2] = $colortop[2]-40 < 0 ?
0 : $colortop[2]-40;
100 $arc = $value/$ratio;
101 $slices[] = array($start, $start+
$arc, $colorbottom, $substep, $colortop, round($arc/3.6, $this->legend_precision
));
107 // make the 3D effect
108 for ($j=$height_3d; $j>0; $j--)
110 foreach ($slices as $i => $slice)
112 if (round($slice[0]) == round ($slice[1]))
115 $center_x_spaced = $center_x;
116 $center_y_spaced = $center_y;
119 $arc_half = $slice[0] +
($slice[1]-$slice[0])/2;
120 $cos = cos(utilities
::deg2rad($arc_half));
121 $sin = sin(utilities
::deg2rad($arc_half));
122 $center_x_spaced = $center_x_spaced +
$cos*$this->spacing
;
123 $center_y_spaced = $center_y_spaced - $sin*$this->spacing
;
128 imageSmoothArc($this->image
, $center_x_spaced, $center_y_spaced+
$j, $width, $height, $color, utilities
::deg2rad($slice[0]), utilities
::deg2rad($slice[1]));
130 // try to determine next color for gradient
133 if ($slice[2][0] != 255)
134 $slices[$i][2][0] = ($slice[2][0]+
$slice[3] > 255) ?
255 : $slice[2][0]+
$slice[3];
138 if ($slice[2][1] != 255)
139 $slices[$i][2][1] = ($slice[2][1]+
$slice[3] > 255) ?
255 : $slice[2][1]+
$slice[3];
143 if ($slice[2][2] != 255)
144 $slices[$i][2][2] = ($slice[2][2]+
$slice[3] > 255) ?
255 : $slice[2][2]+
$slice[3];
151 foreach ($slices as $slice)
153 if (round($slice[0]) == round ($slice[1]))
156 $arc_half = ($slice[0] +
($slice[1]-$slice[0])/2) %
360;
157 $cos = cos(utilities
::deg2rad($arc_half));
158 $sin = sin(utilities
::deg2rad($arc_half));
160 $center_x_spaced = $center_x;
161 $center_y_spaced = $center_y;
164 $center_x_spaced = $center_x_spaced +
$cos*$this->spacing
;
165 $center_y_spaced = $center_y_spaced - $sin*$this->spacing
;
173 imageSmoothArc($this->image
, $center_x_spaced, $center_y_spaced, $width, $height, $color, utilities
::deg2rad($slice[0]), utilities
::deg2rad($slice[1]));
179 // radius of an ellipse
180 $r = $a*$b / sqrt(pow($b,2)*pow($cos,2) +
pow($a,2)*pow($sin,2));
181 $r +
= 15; // padding from the graph
183 $legend_slice_x = $center_x_spaced +
$cos*$r;
184 $legend_slice_y = (($arc_half > 180 AND $arc_half < 360) ?
$center_y_spaced+
$height_3d : $center_y_spaced) - $sin*$r;
186 $text = $slice[5].'%';
188 $box_points = imagettfbbox($this->font_size
, 0, $this->font
, $text);
189 $legend_slice_width = $box_points[4]-$box_points[6];
190 $legend_slice_hheight = ($box_points[3]-$box_points[5]) / 2;
192 if (($arc_half >= 0 AND $arc_half < 90) OR ($arc_half >= 270 AND $arc_half < 360))
194 $legend_slice_x1 = $legend_slice_x+
$legend_slice_hheight;
195 $legend_slice_y1 = $legend_slice_y-$legend_slice_hheight;
196 $legend_slice_x2 = $legend_slice_x+
$legend_slice_width+
$legend_slice_hheight;
197 $legend_slice_y2 = $legend_slice_y+
$legend_slice_hheight+
5;
199 elseif (($arc_half >= 90 AND $arc_half < 180) OR ($arc_half >= 180 AND $arc_half < 270))
201 $legend_slice_x1 = $legend_slice_x-$legend_slice_width-$legend_slice_hheight;
202 $legend_slice_y1 = $legend_slice_y-$legend_slice_hheight;
203 $legend_slice_x2 = $legend_slice_x-$legend_slice_hheight;
204 $legend_slice_y2 = $legend_slice_y+
$legend_slice_hheight+
5;
207 # print percent value
208 utilities
::imagestringbox($this->image
, $this->font
, $this->font_size
, $legend_slice_x1, $legend_slice_y1, $legend_slice_x2, $legend_slice_y2, ALIGN_CENTER
, VALIGN_MIDDLE
, 0, $text, $this->get_color('font_color'));
214 //$this->draw_legend('colors', 0, $center_x+$width/2-20+$legend_slice_width*3, $this->height/2-$height/2);
215 $this->draw_legend('colors', 0, 20, $this->height
/2+
62);