3 class BarChart
extends Chart
{
5 protected $type = NULL; // NULL, stacked, multiple
7 protected $bar_width = 25;
9 protected $approx_line_gap = 40; // how much space should be approximately between each line
11 protected $plot_bg_color = array('#fff', '#ccc'); // also supports arrays as array('#fff', '#333', '#432', ...) for gradients
13 protected $plot_bg_by_lines = FALSE; // if set to true bg colors will be rendered in areas separated by lines (useful for gradients)
15 protected $background_style = 'lines'; // [dotted / lines / NULL]
17 protected $legend_y = ''; // y axis legend
19 protected $legend_x = ''; // x axis legend
21 protected $bar_legend = TRUE; // display legend above the bars?
23 protected $vertical_bar_lines = false; // display vertical lines in the middle of the bars?
26 public function __construct($width=NULL, $height=NULL)
28 parent
::__construct($width, $height);
30 $this->set_margins(5);
32 $this->colors
['bar_color'] = array('#e0d62e', NULL, NULL);
33 $this->colors
['bar_border_color'] = array('#747014', 10, NULL);
34 $this->colors
['line_color'] = array('#dfdfdf', NULL, NULL); // primary color of lines
35 $this->colors
['line_color2'] = array('#969696', NULL, NULL); // for short lines by the legend for example
38 public function set_bar_legend($value)
40 $this->bar_legend
= $value;
43 public function set_background_style($value)
45 $this->background_style
= $value;
48 public function set_legend_y($value)
50 $this->legend_y
= $value;
53 public function set_legend_x($value)
55 $this->legend_x
= $value;
58 // it's approximate values because gap will be exactly counted so it's nicely drawn. see ( --gap-line-- )
59 public function set_approx_line_gap($value)
61 $this->approx_line_gap
= $value;
64 // also supports arays for gradients
65 public function set_plot_bg_color($values, $by_lines = FALSE)
67 $this->plot_bg_color
= $values;
68 $this->plot_bg_by_lines
= $by_lines;
71 public function set_bar_width($value)
73 $this->bar_width
= $value;
76 public function draw()
80 if ($this->type
== 'stacked')
83 foreach ($this->values
as $v)
84 $values[] = array_sum($v);
88 $values = $this->values
;
91 $max_value = utilities
::max($values);
92 $min_value = utilities
::min($values);
94 $max = max($max_value, abs($min_value));
96 $box_points = imagettfbbox($this->font_size
, 0, $this->font
, '0');
97 $fheight = $box_points[3]-$box_points[5]; // font height
98 $vpp = $max/$this->height
; // get approximate value per px -- exact value could be get only later so try it this way
99 $plus = ceil( $vpp * ($fheight +
($this->bar_legend ?
$fheight : 0)) * 2.3 );
101 $max_value +
= $max_value > 0 ?
$plus : 0; // add PLUS so the legend for bars is in the graph borders if there is any
102 $min_value -= $min_value < 0 ?
$plus : 0; // subtract PLUS so the legend for bars is in the graph borders if there is any
104 $max = max($max_value, abs($min_value));
106 // get the next "nice" value for max
108 while (pow(10, ++
$pow) < $max);
109 $step = pow(10, $pow-2);
113 $from = round($max_value, -$pow+
2);
114 if ($from < $max_value) // if it was rounded down
123 // get the prev "nice" value for min
126 $from = round(abs($min_value), -$pow+
2);
127 if ($from < abs($min_value)) // if it was rounded down
136 # discard max_value calculated above and always keep
137 # it at 100 for the SLA reports
140 // -- start: sizes of titles and labels of axis
143 if (!empty($this->legend_y
))
145 $box_points = imagettfbbox($this->font_size
, 0, $this->font
, $this->legend_y
);
146 $y_legend_width = $box_points[3]-$box_points[5]; // y-axis legend height
147 $y_legend_gap = $this->margin_left
;
149 $this->margin_left +
= ($y_legend_width*2)-30; // modify size of the left margin
153 $box_points = imagettfbbox($this->font_size
, 0, $this->font
, max($max_value, abs($min_value)).'-.0'); // - added for minus, . added for point, 0 added for decimal number
154 $y_legend_labels_width = $box_points[4]-$box_points[6]; // y-axis labels width
155 $y_legend_labels_height = $box_points[3]-$box_points[5]; // y-axis labels height
157 $this->margin_left +
= $y_legend_labels_width +
5; // modify size of the left margin
160 if (!empty($this->legend_x
))
162 $box_points = imagettfbbox($this->font_size
, 0, $this->font
, $this->legend_x
);
163 $x_legend_height = $box_points[3]-$box_points[5];
164 $x_legend_gap = $this->margin_bottom
;
166 $this->margin_bottom +
= $x_legend_height*2 +
2;
170 $box_points = imagettfbbox($this->font_size
, 0, $this->font
, implode(array_keys($this->values
)));
171 $x_legend_labels_height = $box_points[3]-$box_points[5]; // y-axis labels height
173 $this->margin_bottom +
= $x_legend_labels_height +
5; // modify size of the left margin
175 // -- end: sizes of titles and labels of axis
177 if (!empty($this->legend
))
178 $this->margin_right +
= 15;
180 $plot_sizes = $this->get_plot_area(); // size of the graph area
182 if (($max_value+
abs($min_value)) == 0)
183 $ratio = $plot_sizes[1]; // default value when there are only zero data
185 $ratio = $plot_sizes[1]/($max_value+
abs($min_value)); // how much value is for one pixel? -- sorry for the bad English
187 $horizontal_lines = floor($plot_sizes[1]/$this->approx_line_gap
); // --gap-line-- count exact count of the horizontal lines
188 $horizontal_gap = $plot_sizes[1]/$horizontal_lines; // count exact space between these lines
191 // draw graph background
192 if (!is_array($this->plot_bg_color
))
193 { // draw solid color
194 $plot_bg_color_rgb = utilities
::hex2rgb($this->plot_bg_color
);
195 $plot_bg_color = imagecolorallocate($this->image
, $plot_bg_color_rgb[0], $plot_bg_color_rgb[1], $plot_bg_color_rgb[2]);
196 imagefilledrectangle($this->image
, $this->margin_left
, $this->margin_top
, $this->width
-1-$this->margin_right
, $this->height
-1-$this->margin_bottom
, $plot_bg_color);
200 if (!$this->plot_bg_by_lines
)
201 { // one for the whole bg
202 $gradient_height = $plot_sizes[1]; // how much should gradient take?
206 { // one for each horizontal gap separated by y axis lines
207 $gradient_height = ceil($horizontal_gap); // how much should gradient take?
208 $goesto = $horizontal_lines-1;
210 for ($i=0; $i<=$goesto; $i++
)
212 $color_index = ($i*2)%count
($this->plot_bg_color
);
213 $c1 = $this->plot_bg_color
[$color_index]; // start color
214 $c2 = isset($this->plot_bg_color
[$color_index+
1]) ?
$this->plot_bg_color
[$color_index+
1] : $this->plot_bg_color
[$color_index]; // end color
215 $gradient = new Gradient(NULL, $plot_sizes[0], $gradient_height, 'vertical', $c1, $c2, 0); // make gradient
216 imagecopymerge($this->image
, $gradient->image
, $this->margin_left
, $this->margin_top+
$gradient_height*$i, 0, 0, $this->width
-$this->margin_left
-$this->margin_right
, $gradient_height, 100); // copy the gradient to the graph
220 if (!empty($this->legend_y
))
221 // draw y axis legend
222 utilities
::imagestringbox($this->image
, $this->font
, $this->font_size
, $y_legend_gap-10, $this->margin_top
, $y_legend_gap+
$y_legend_width, $this->height
-$this->margin_bottom
, ALIGN_CENTER
, VALIGN_MIDDLE
, 0, $this->legend_y
, $this->get_color('font_color2'), TRUE);
223 if (!empty($this->legend_x
))
224 // draw x axis legend
225 utilities
::imagestringbox($this->image
, $this->font
, $this->font_size
, $this->margin_left
, $this->height
-$x_legend_gap-$x_legend_height, $this->width
-$this->margin_right
, $this->height
-$x_legend_gap, ALIGN_CENTER
, VALIGN_MIDDLE
, 0, $this->legend_x
, $this->get_color('font_color2'));
227 $style = array($this->get_color('line_color'), $this->get_color('line_color'), $this->get_color('line_color'), $this->get_color('line_color'), $this->get_color('line_color'), IMG_COLOR_TRANSPARENT
, IMG_COLOR_TRANSPARENT
, IMG_COLOR_TRANSPARENT
, IMG_COLOR_TRANSPARENT
, IMG_COLOR_TRANSPARENT
);
228 imagesetstyle($this->image
, $style); // set style of the line
230 for ($i=0; $i<=$horizontal_lines; $i++
)
232 $y = $this->height
- $this->margin_bottom
- $horizontal_gap * $i;
233 imageline($this->image
, $this->margin_left
, $y, $this->width
-$this->margin_right
, $y, IMG_COLOR_STYLED
); // draw the line in graph
234 imageline($this->image
, $this->margin_left
-2, $y, $this->margin_left
, $y, $this->get_color('line_color2')); // draw the graph by the legend
236 $v = round($horizontal_gap * $i / $ratio, 0) +
$min_value;
237 $y_legend_y = $y-round($y_legend_labels_height/2);
239 utilities
::imagestringbox($this->image
, $this->font
, $this->font_size
, $this->margin_left
-$y_legend_labels_width, $y_legend_y, $this->margin_left
-6, $y_legend_y+
$y_legend_labels_height, ALIGN_RIGHT
, VALIGN_MIDDLE
, 0, $v, $this->get_color('font_color'));
243 // draw graph borders
244 imageline($this->image
, $this->margin_left
, $this->margin_top
, $this->margin_left
, $this->height
-$this->margin_bottom
, $this->get_color('line_color2')); // left
245 imageline($this->image
, $this->margin_left
, $this->height
-$this->margin_bottom
, $this->width
-$this->margin_right
, $this->height
-$this->margin_bottom
, $this->get_color('line_color2')); // bottom
246 imageline($this->image
, $this->margin_left+
1, $this->margin_top
, $this->width
-$this->margin_right
, $this->margin_top
, $this->get_color('line_color')); // top
247 imageline($this->image
, $this->width
-$this->margin_right
, $this->margin_top
, $this->width
-$this->margin_right
, $this->height
-$this->margin_bottom
-1, $this->get_color('line_color')); // right
249 // draw the background image
250 if (!empty($this->background_style
)) {
251 switch ($this->background_style
)
254 $bgs_color = $this->get_color('shade_color2');
256 $bgs_color = $this->get_color('shade_color3');
258 utilities
::imagefilledrectanglestyled($this->image
, $this->margin_left
, $this->margin_top
, $this->width
-$this->margin_right
, $this->height
-$this->margin_bottom
, $this->background_style
, $bgs_color);
261 $zeroline = abs($min_value)*$ratio; // where should be y=0 placed?
262 imagefilledrectangle($this->image
, $this->margin_left
, $this->height
-$this->margin_bottom
-$zeroline, $this->width
-$this->margin_right
, $this->height
-$this->margin_bottom
-$zeroline, $this->get_color('shade_color')); // draw shade of bar
264 $this->draw_values($zeroline, $ratio); // draw bars
265 $this->draw_legend('bar_color'); // draw box with the legend
268 protected function draw_values($zeroline, $ratio)
270 $plot_sizes = $this->get_plot_area();
271 $font_bar_legend = $this->font_size
< 1 ?
$this->font_size
: $this->font_size
-1;
273 $total_bars = count($this->values
); // count of all bars
274 $gap = ($plot_sizes[0] - $total_bars*$this->bar_width
) / ($total_bars+
1); // gap between bars
278 foreach ($this->values
AS $key => $v)
280 $x1 = $this->margin_left +
$gap +
$i*($gap+
$this->bar_width
);
281 $x2 = $x1 +
$this->bar_width
;
282 $y2 = $this->height
- $this->margin_bottom
- $zeroline;
283 $y1 = $y2 - $v*$ratio;
285 if ($this->vertical_bar_lines
)
286 imageline($this->image
, $x1+
$this->bar_width
/2, $this->margin_top
-1, $x1+
$this->bar_width
/2, $this->height
-$this->margin_bottom
-1, IMG_COLOR_STYLED
);
288 imagefilledrectangle($this->image
, $x1, $y1, $x2, $y2, $this->get_color('bar_color')); // draw bar
289 $this->add_occupied($x1, $y1, $x2, $y2);
291 if ($this->get_color('bar_border_color'))
293 imageline($this->image
, $x1, $y1, $x1, $y2, $this->get_color('bar_border_color')); // left
294 imageline($this->image
, $x1, $y1, $x2, $y1, $this->get_color('bar_border_color')); // top
295 imageline($this->image
, $x2, $y1, $x2, $y2, $this->get_color('bar_border_color')); // right
299 imagefilledrectangle($this->image
, $x2, $y1+
($v > 0 ?
1 : -1), $x2+
1, $y2, $this->get_color('shade_color')); // draw shade of bar
301 $box_points = imagettfbbox($this->font_size
, 0, $this->font
, $v);
302 $bar_middle = $x1 +
$this->bar_width
/2;
303 $bar_legend_hwidth = ($box_points[4]-$box_points[6]) / 2;
304 $fheight = $box_points[3]-$box_points[5];
307 if ($this->bar_legend
)
311 utilities
::imagestringbox($this->image
, $this->font
, $font_bar_legend, $bar_middle-$bar_legend_hwidth, $y1-$fheight-5, $bar_middle+
$bar_legend_hwidth, $y1, ALIGN_CENTER
, VALIGN_MIDDLE
, 0, $v, $this->get_color('font_color3'));
312 $this->add_occupied($bar_middle-$bar_legend_hwidth, $y1-$fheight-5, $bar_middle+
$bar_legend_hwidth, $y1);
316 utilities
::imagestringbox($this->image
, $this->font
, $font_bar_legend, $bar_middle-$bar_legend_hwidth, $y1+
5, $bar_middle+
$bar_legend_hwidth, $y1+
$fheight+
5, ALIGN_CENTER
, VALIGN_MIDDLE
, 0, $v, $this->get_color('font_color3'));
317 $this->add_occupied($bar_middle-$bar_legend_hwidth, $y1+
5, $bar_middle+
$bar_legend_hwidth, $y1+
$fheight+
5);
322 $box_points = imagettfbbox($this->font_size
, 0, $this->font
, $key);
323 $y_legend_hwidth = ($box_points[4]-$box_points[6]) / 2;
326 utilities
::imagestringbox($this->image
, $this->font
, $this->font_size
, $bar_middle-$y_legend_hwidth, $this->margin_top+
$plot_sizes[1]+
5, $bar_middle+
$y_legend_hwidth, $this->margin_top+
$plot_sizes[1]+
5+
$fheight, ALIGN_CENTER
, VALIGN_MIDDLE
, 0, $key, $this->get_color('font_color'));