├── README.md
├── bin
└── phpGraph.php
├── composer.json
└── samples.php
/README.md:
--------------------------------------------------------------------------------
1 | phpGraph
2 | ========
3 |
4 | Writing svg histogram with php
5 |
6 | How to use ?
7 | ------------
8 |
9 | First, data must be in an php array (one or two dimensions).
10 | Then, an instance of phpGraph class have to be called after an inclusion of phpGraph.php file in your project.
11 | Then, the main method called draw is used, with or withour options. It's up to you.
12 |
13 | Add phpGraph_style.css to header of your page for display graph.
14 |
15 |
16 |
17 |
18 |
19 |
20 | phpGraph
21 |
22 |
23 | (...)
24 |
25 | By default, it's a line histogram which is displaying.
26 |
27 | To resume :
28 |
29 | 10,
34 | 'serie 2' => 38,
35 | 'serie 3' => 23,
36 | 'serie 4' => -15
37 | );
38 |
39 | $G = new phpGraph();
40 |
41 | echo $G->draw($data);
42 | ?>
43 |
44 | Options available :
45 | -------------------
46 |
47 | //All options available
48 | $options = array(
49 | 'width' => null,// (int) width of grid
50 | 'height' => null,// (int) height of grid
51 | 'paddingTop' => 10,// (int)
52 | 'type' => 'line',// (string) line, bar, pie, ring, stock or h-stock (todo curve)
53 | 'steps' => null,// (int) 2 graduations on y-axis are separated by $steps units. "steps" is automatically calculated but we can set the value with integer. No effect on stock and h-stock charts
54 | 'filled' => true,// (bool) to fill lines/histograms/disks
55 | 'tooltips' => false,// (bool) to show tooltips
56 | 'circles' => true,// (bool) to show circles on graph (lines or histograms). No effect on stock and h-stock charts
57 | 'stroke' => '#3cc5f1',// (string) color of lines by default. Use an array to personalize each line
58 | 'background' => "#ffffff",// (string) color of grid background. Don't use short notation (#fff) because of $this->__genColor();
59 | 'opacity' => '0.5',// (float) between 0 and 1. No effect on stock and h-stock charts
60 | 'gradient' => null,// (array) 2 colors from left to right
61 | 'titleHeight' => 0,// (int) Height of main title
62 | 'tooltipLegend' => null,// (string or array) Text display in tooltip with y value. Each text can be personalized using an array. No effect on stock and h-stock charts
63 | 'legends' => null,// (string or array or bool) General legend for each line/histogram/disk displaying under diagram
64 | 'title' => null,// (string) Main title. Title wil be displaying in a tooltip too.
65 | 'radius' => 100,// (int) Radius of pie
66 | 'diskLegends' => false,// (bool) to display legends around a pie
67 | 'diskLegendsType' => 'label',// (string) data, pourcent or label to display around a pie as legend
68 | 'diskLegendsLineColor' => 'darkgrey',// (string) color of lines which join pie to legends
69 | 'responsive' => true,// (bool) to avoid svg to be responsive (dimensions fixed)
70 | 'paddingLegendX' => 10,//We add 10 units in viewbox to display x legend correctly
71 | );
72 |
73 | See [samples.php](http://www.ecyseo.net/?static8/phpgraph) for more details.
74 |
75 | [Page of project on github](http://jerrywham.github.io/phpGraph/)
76 |
77 | Licence :
78 | ---------
79 | [CONTRAT DE LICENCE DE LOGICIEL LIBRE CeCILL version 2.1](http://www.cecill.info/licences/Licence_CeCILL_V2.1-fr.txt)
80 |
81 | Change log :
82 | ---------
83 | 2015-01-29
84 | * [BUG] calcul of position of points for lines and bars
85 | * [BUG] position of legend for pies and rings
86 | * [BUG] put in cache
87 |
88 | 2015-01-28
89 | * [+] css file is not mandatory. Style is included in svg and can be modified via setCss() method
90 | * [+] new option : diskLegendsLineColor
91 | * [BUG] colors of legends
92 | * [BUG] position of lines between pie and labels
93 |
--------------------------------------------------------------------------------
/bin/phpGraph.php:
--------------------------------------------------------------------------------
1 |
25 | * @copyright 2009-2019 Cyril MAGUIRE,
26 | * @license Licensed under the CeCILL v2.1 license. http://www.cecill.info/licences.fr.html
27 | */
28 |
29 | class phpGraph {
30 |
31 | # Basic css style
32 | protected $css = '
33 | /**/.draw {
34 | width:70%;/*Adjust this value to resize svg automatically*/
35 | margin:auto;
36 | }
37 | /**/svg {/*width and height of svg is 100% of dimension of its parent (draw class here)*/
38 | display: block;
39 | margin:auto;
40 | margin-bottom: 50px;
41 | }
42 | /**/.graph-title {
43 | stroke-width:4;
44 | stroke:transparent;
45 | fill:#000033;
46 | font-size: 1.2em;
47 | }
48 | /**/.graph-grid {
49 | stroke-width:1;
50 | stroke:#c4c4c4;
51 | }
52 | /**/.graph-stroke {
53 | stroke-width:2;
54 | stroke:#424242;
55 | }
56 | /**/.graph-legends {}
57 | /**/.graph-x text,
58 | /**/.graph-y text {
59 | font-size:0.5em;
60 | }
61 | /**/.graph-active .graph-legend {
62 | font-size:0.6em;
63 | }
64 | /**/.graph-legend-stroke {}
65 | /**/.graph-line {
66 | stroke-linejoin:round;
67 | stroke-width:2;
68 | }
69 | /**/.graph-fill {
70 | stroke-width:0;
71 | }
72 | /**/.graph-bar {}
73 | /**/.graph-point {
74 | stroke-width:1;
75 | fill:#fff;
76 | fill-opacity:1;
77 | stroke-opacity:1;
78 | }
79 | /**/.graph-point-active:hover {
80 | stroke-width:5;
81 | transition-duration:.9s;
82 | cursor: pointer;
83 | }
84 | /**/title.graph-tooltip {
85 | background-color:#d6d6d6;
86 | }
87 | /**/.graph-pie {
88 | cursor: pointer;
89 | stroke-width:1;
90 | stroke:#fff;
91 | }
92 | /**/text {
93 | fill:#000;
94 | font-size:0.7em;
95 | }
96 | ';
97 |
98 | protected $options = array(
99 | 'width' => null,// (int) width of grid
100 | 'height' => null,// (int) height of grid
101 | 'paddingTop' => 10,// (int)
102 | 'type' => 'line',// (string) line, bar, pie, ring, stock or h-stock (todo curve)
103 | 'steps' => null,// (int) 2 graduations on y-axis are separated by $steps units. "steps" is automatically calculated but we can set the value with integer. No effect on stock and h-stock charts
104 | 'filled' => true,// (bool) to fill lines/histograms/disks
105 | 'tooltips' => false,// (bool) to show tooltips
106 | 'circles' => true,// (bool) to show circles on graph (lines or histograms). No effect on stock and h-stock charts
107 | 'stroke' => '#3cc5f1',// (string) color of lines by default. Use an array to personalize each line
108 | 'background' => "#ffffff",// (string) color of grid background. Don't use short notation (#fff) because of $this->__genColor();
109 | 'opacity' => '0.5',// (float) between 0 and 1. No effect on stock and h-stock charts
110 | 'gradient' => null,// (array) 2 colors from left to right
111 | 'titleHeight' => 0,// (int) Height of main title
112 | 'tooltipLegend' => null,// (string or array) Text display in tooltip with y value. Each text can be personalized using an array. No effect on stock and h-stock charts
113 | 'legends' => null,// (string or array or bool) General legend for each line/histogram/disk displaying under diagram
114 | 'title' => null,// (string) Main title. Title wil be displaying in a tooltip too.
115 | 'radius' => 100,// (int) Radius of pie
116 | 'diskLegends' => false,// (bool) to display legends around a pie
117 | 'diskLegendsType' => 'label',// (string) data, pourcent or label to display around a pie as legend
118 | 'diskLegendsLineColor' => 'darkgrey',// (string) color of lines which join pie to legends
119 | 'responsive' => true,// (bool) to avoid svg to be responsive (dimensions fixed)
120 | 'paddingLegendX' => 10,//We add 10 units in viewbox to display x legend correctly
121 | 'paddingLegendY' => 0,//Padding to display y legend correctly, if needed, for pie and ring
122 | 'transform' => null,//Transformation of the text of the legend
123 | 'marginTop' => 0,//Margin of the legend when use transform
124 | );
125 | # authorized types
126 | protected $types = array('line','line','bar','pie','ring','stock','h-stock');
127 | protected $periodOfCache = 1;//A REGLER ET A VERIFIER
128 |
129 | private $DEBUG = false;
130 | private $L_ERROR_FILE_NOT_FOUND = 'ERROR FILE NOT FOUND';
131 | private $SIG_ROOT = dirname(__FILE__).DIRECTORY_SEPARATOR;
132 | private $SIG_CORE = 'core'.DIRECTORY_SEPARATOR;
133 |
134 |
135 | //protected $colors = array();
136 |
137 | /**
138 | * Constructor
139 | *
140 | * @param $width integer Width of grid
141 | * @param $height integer Height of grid
142 | * @param $options array Options
143 | * @return stdio
144 | *
145 | * @author Cyril MAGUIRE
146 | **/
147 | public function __construct($width=600,$height=300,$options=array()) {
148 | if (isset($options['ROOT']) && is_string($options['ROOT'])) {
149 | $this->SIG_ROOT = $options['ROOT'];
150 | unset($options['ROOT']);
151 | }
152 | $this->SIG_CORE = $this->SIG_ROOT.$this->SIG_CORE;
153 | if (!empty($options)) {
154 | $this->options = $options;
155 | }
156 | if (!empty($width)) {
157 | $this->options['width'] = $width;
158 | }
159 | if (!empty($height)) {
160 | $this->options['height'] = $height;
161 | }
162 | if (is_string($this->options['stroke']) && substr($this->options['stroke'], 0,1) == '#') {
163 | $this->options['stroke'] = array(0=>substr($this->options['stroke'],0,7));
164 | }
165 | if (is_string($this->options['type']) && in_array($this->options['type'], $this->types)) {
166 | $this->options['type'] = array(0=>$this->options['type']);
167 | }
168 | }
169 |
170 | /**
171 | * To add your own style
172 | * @param $css string your css
173 | * @return string css
174 | *
175 | * @author Cyril MAGUIRE
176 | */
177 | public function setCss($css) {
178 | if (is_string($css) && !empty($css)) {
179 | $this->css .= $css;
180 | }
181 | }
182 |
183 | /**
184 | * Main function
185 | * @param $data array Uni or bidimensionnal array
186 | * @param $options array Array of options
187 | * @param $putInCache string path of directory where cache will be recorded
188 | * @param $id string index of svg tag
189 | * @return string SVG
190 | *
191 | * @author Cyril MAGUIRE
192 | */
193 | public function draw($data,$options=array(),$putInCache=false,$id=false,$txt=false) {
194 |
195 | if ($id) {
196 | $this->css = str_replace('/**/', '#'.$id.' ', $this->css);
197 | }
198 |
199 | # Cache
200 | $nameOfFiles = glob($putInCache.'*.svg');
201 | if ($putInCache != false && isset($nameOfFiles[0])) {
202 | $stat = stat($nameOfFiles[0]);
203 | if ($stat['mtime'] > (time() - $this->periodOfCache) ) {
204 | return file_get_contents($nameOfFiles[0]).($id ? $downloadLink : '');
205 | }
206 | }
207 | $return = '';
208 |
209 | $options = array_merge($this->options,$options);
210 |
211 | extract($options);
212 |
213 | if ($title) {
214 | $options['titleHeight'] = $titleHeight = 40;
215 | }
216 | if ($opacity < 0 || $opacity > 1) {
217 | $options['opacity'] = 0.5;
218 | }
219 | if (!is_string($diskLegendsLineColor)) {
220 | $diskLegendsLineColor = 'darkgrey';
221 | }
222 |
223 | $HEIGHT = $height+$titleHeight+$paddingTop;
224 |
225 | $heightLegends = 0;
226 | if (isset($legends) && !empty($legends)) {
227 | $heightLegends = count($legends)*30+2*$paddingTop;
228 | }
229 |
230 | $pie = '';
231 |
232 | if ($type != 'pie' && $type != 'ring') {
233 | # looking for min and max
234 | extract($this->__minMax($data,$type));
235 | $options['type'] = $type;
236 |
237 | extract($this->__xAxisConfig($type,$width,$max,$Xmax,$Xmin,$lenght,$options));
238 |
239 | $base10 = strlen(abs($max));
240 | $steps = 2 * (($base10 >= 2 && $max >= 50) ? str_pad(1,($base10-1),0,STR_PAD_RIGHT) : 1);
241 |
242 | $options['steps'] = $steps;
243 |
244 | if ($min < 0) {
245 | $unitY = round($height/abs(($max+$steps)-$min),PHP_ROUND_HALF_UP);
246 | } else {
247 | $unitY = round($height/($max+$steps),PHP_ROUND_HALF_UP);
248 | }
249 | $gridV = $gridH = '';
250 | $x = $y = '';
251 |
252 | $headerDimensions = $this->__headerDimensions($widthViewBox,$HEIGHT,$heightLegends,$titleHeight,$paddingTop,$paddingLegendX,$lenght,$stepX);
253 |
254 | # Size of canevas will be bigger than grid size to display legends
255 | $return = $this->__header($headerDimensions,$responsive,$id);
256 |
257 | if ($type == 'stock' || (is_array($type) && in_array('stock',$type)) ) {
258 | $plotLimit = $this->__stockDef();
259 | }
260 | if ($type == 'h-stock' || (is_array($type) && in_array('h-stock',$type)) ) {
261 | $plotLimit = $this->__hstockDef();
262 | }
263 | # we draw the grid
264 | $return .= $this->__svgGrid($gradient,$width,($height+$paddingTop),($paddingTop+$titleHeight));
265 |
266 | if ($title) {
267 | $return .= $this->__titleDef($title,$width,$titleHeight);
268 | }
269 | # Legends x axis and vertical grid
270 | extract($this->__XAxisDef($type,$Xmin,$Xmax,$XM,$stepX,$unitX,$HEIGHT,$paddingTop,$titleHeight,$labels,$lenght, $transform));
271 |
272 | # Legendes y axis and horizontal grid
273 | extract($this->__YAxisDef($type,$width,$min,$max,$steps,$HEIGHT,$titleHeight,$paddingTop,$paddingLegendX,$unitY,$labels));
274 | //Grid
275 | $return .= "\t".''."\n";
276 | $return .= $gridH."\n";
277 | $return .= $gridV;
278 | $return .= "\t".''."\n";
279 |
280 | $return .= $x;
281 | $return .= $y;
282 | if (!$multi) {
283 | if (is_array($type) && count($type) == 1) {
284 | $type = $type[0];
285 | $options['type'] = $type;
286 | }
287 | $options['stroke'] = is_array($stroke) ? $stroke[0] : $stroke;
288 | switch ($type) {
289 | case 'line':
290 | $return .= $this->__drawLine($data,$height,$HEIGHT,$stepX,$unitY,$lenght,$min,$max,$options);
291 | break;
292 | case 'bar':
293 | $return .= $this->__drawBar($data,$height,$HEIGHT,$stepX,$unitY,$lenght,$min,$max,$options);
294 | break;
295 | default:
296 | $return .= $this->__drawLine($data,$height,$HEIGHT,$stepX,$unitY,$lenght,$min,$max,$options);
297 | break;
298 | }
299 | } else {
300 | $i = 1;
301 | foreach ($data as $line => $datas) {
302 | if (!isset($type[$line]) && !is_string($type) && is_numeric($line)) {
303 | $type[$line] = 'line';
304 | }
305 | if (!isset($type[$line]) && !is_string($type) && !is_numeric($line)) {
306 | $type[$line] = 'stock';
307 | }
308 | if (is_string($options['type'])) {
309 | $type = array();
310 | $type[$line] = $options['type'];
311 | }
312 | if (!isset($tooltipLegend[$line])) {
313 | $options['tooltipLegend'] = '';
314 | } else {
315 | $options['tooltipLegend'] = $tooltipLegend[$line];
316 | }
317 | if (!isset($stroke[$line])) {
318 | $stroke[$line] = $this->__genColor();
319 | }
320 | $options['stroke'] = $STROKE = $stroke[$line];
321 | $options['fill'] = $stroke[$line];
322 | switch ($type[$line]) {
323 | case 'line':
324 | $return .= $this->__drawLine($datas,$height,$HEIGHT,$stepX,$unitY,$lenght,$min,$max,$options);
325 | break;
326 | case 'bar':
327 | $return .= $this->__drawBar($datas,$height,$HEIGHT,$stepX,$unitY,$lenght,$min,$max,$options);
328 | break;
329 | case 'stock':
330 | $id = rand();
331 | $return .= str_replace(array('id="plotLimit"','stroke=""'), array('id="plotLimit'.$id.'"','stroke="'.$stroke[$line].'"'), $plotLimit);
332 | $return .= $this->__drawStock($data,$height,$HEIGHT,$stepX,$unitY,$lenght,$min,$max,$options,$i,$labels,$id);
333 | $i++;
334 | break;
335 | case 'h-stock':
336 | $id = rand();
337 | $return .= str_replace(array('id="plotLimit"','stroke=""'), array('id="plotLimit'.$id.'"','stroke="'.$stroke[$line].'"'), $plotLimit);
338 | $return .= $this->__drawHstock($data,$HEIGHT,$stepX,$unitX,$unitY,$lenght,$Xmin,$Xmax,$options,$i,$labels,$id);
339 | $i++;
340 | break;
341 | case 'ring':
342 | $options['subtype'] = 'ring';
343 | case 'pie':
344 | $options['multi'] = $multi;
345 | if (is_array($stroke)) {
346 | $options['stroke'] = $stroke[$line];
347 | $options['fill'] = $stroke;
348 | }
349 | if (is_array($legends)) {
350 | $options['legends'] = $legends[$line];
351 | }
352 | $pie .= $this->__drawDisk($datas,$options,$id);
353 | $pie .= "\n".''."\n";
354 | break;
355 | default:
356 | $return .= $this->__drawLine($datas,$height,$HEIGHT,$stepX,$unitY,$lenght,$min,$max,$options);
357 | break;
358 | }
359 | }
360 | }
361 | # legends
362 | $return .= $this->__legendsDef($legends,$type,$stroke,$HEIGHT,$paddingTop,$marginTop);
363 | $return .= "\n".''."\n";
364 | $return .= $pie;
365 | } else {
366 | $options['tooltipLegend'] = array();
367 | if ($tooltipLegend && !is_array($tooltipLegend)) {
368 | foreach ($data as $key => $value) {
369 | $options['tooltipLegend'][] = $tooltipLegend;
370 | }
371 | }
372 | if ($tooltipLegend && is_array($tooltipLegend)) {
373 | $options['tooltipLegend'] = $tooltipLegend;
374 | }
375 | $options['stroke'] = array();
376 | if (isset($stroke) && !is_array($stroke)) {
377 | foreach ($data as $key => $value) {
378 | $options['stroke'][] = $stroke;
379 | }
380 | }
381 | if (isset($stroke) && is_array($stroke)) {
382 | $options['stroke'] = $stroke;
383 | }
384 | foreach ($data as $line => $datas) {
385 | if (is_array($datas)) {
386 | if (is_array($stroke)) {
387 | $options['stroke'] = $stroke[$line];
388 | $options['fill'] = $stroke;
389 | }
390 | if (is_array($legends)) {
391 | $options['legends'] = $legends[$line];
392 | }
393 | $return .= $this->__drawDisk($datas,$options,$id);
394 | $return .= "\n".''."\n";
395 | $multi = true;
396 | } else {
397 | $multi = false;
398 | }
399 | }
400 | if (!$multi) {
401 | if (is_array($stroke)) {
402 | $options['stroke'] = $stroke;
403 | $options['fill'] = $stroke;
404 | }
405 | if (is_array($legends)) {
406 | $options['legends'] = $legends;
407 | }
408 | $return .= $this->__drawDisk($data,$options,$id);
409 | $return .= "\n".''."\n";
410 | }
411 |
412 | }
413 |
414 | $this->colors = array();
415 | if ($putInCache && $stat['mtime'] > (time() - $this->periodOfCache) ) {
416 | $this->putInCache(trim($return),md5(implode('',$nameOfFile)),$putInCache);
417 | //file_put_contents($putInCache, trim($return));
418 | }
419 | return $return.($id ? $downloadLink : '');
420 | }
421 |
422 | /**
423 | * To draw lines
424 | * @param $data array Unidimensionnal array
425 | * @param $height integer Height of grid
426 | * @param $HEIGHT integer Height of grid + title + padding top
427 | * @param $stepX integer Unit of x-axis
428 | * @param $unitY integer Unit of y-axis
429 | * @param $lenght integer Size of data array
430 | * @param $min integer Minimum value of data
431 | * @param $max integer Maximum value of data
432 | * @param $options array Options
433 | * @return string Path of lines (with options)
434 | *
435 | * @author Cyril MAGUIRE
436 | */
437 | protected function __drawLine($data,$height,$HEIGHT,$stepX,$unitY,$lenght,$min,$max,$options) {
438 | $return = '';
439 |
440 | extract($options);
441 |
442 | $this->colors[] = $options['stroke'];
443 |
444 | //Ligne
445 | $i = 0;
446 | $c = '';
447 | $t = '';
448 | $path = "\t\t".'';
479 | }
480 | # Line
481 | $c1 = $this->__c($coordonneesCircle1,$stroke);
482 | $c2 = $this->__c($coordonneesCircle2,$stroke);
483 | if ($value != $max) {
484 | if ($value == $min) {
485 | if ($i == 0) {
486 | // if ($min<=0) {
487 | // $path .= 'M '.$coordonnees2.' L';
488 | // //Tooltips and circles
489 | // $c .= $c2;
490 | // } else {
491 | $path .= 'M '.$coordonnees1.' L';
492 | //Tooltips and circles
493 | $c .= $c1;
494 | // }
495 | } else {
496 | $path .= "\n\t\t\t\t".$coordonnees1;
497 | //Tooltips and circles
498 | $c .= $c1;
499 | }
500 | } else {
501 | if ($i == 0) {
502 | $path .= 'M '.$coordonnees1.' L';
503 | //Tooltips and circles
504 | $c .= $c1;
505 | } else {
506 | $path .= "\n\t\t\t\t".$coordonnees1;
507 | //Tooltips and circles
508 | $c .= $c1;
509 | }
510 | }
511 | } else {
512 | //Line
513 | if ($i == 0) {
514 | $path .= 'M '.($i * $stepX + 50).' '.($V == 0 ? $HEIGHT + $paddingTop : ($titleHeight + ($HEIGHT - $unitY*$V))).' L';
515 | //Tooltips and circles
516 | $c .= "\n\t\t\t".'';
517 | } else {
518 | $path .= "\n\t\t\t\t".$coordonnees1;
519 | //Tooltips and circles
520 | $c .= "\n\t\t\t".'';
521 | }
522 |
523 | }
524 | $i++;
525 | //End tooltips
526 | if($tooltips == true) {
527 | $c .= "\n\t\t\t".''.(is_array($tooltipLegend) ? $tooltipLegend[$i] : $tooltipLegend).$value.''."\n\t\t".'';
528 | }
529 | }
530 | if ($opacity > 0.8 && $filled === true) {
531 | $tmp = $stroke;
532 | $stroke = '#a1a1a1';
533 | }
534 | //End of line
535 | $pathLine = '" class="graph-line" stroke="'.$stroke.'" fill="#fff" fill-opacity="0"/>'."\n";
536 | //Filling
537 | if ($filled === true) {
538 | if ($min<=0) {
539 | $path .= "\n\t\t\t\t".(($i - 1) * $stepX + 50).' '.($HEIGHT + ($unitY)*($min-$value) + ($unitY * $value)).' 50 '.($HEIGHT + ($unitY)*($min-$value) + ($unitY * $value))."\n\t\t\t\t";
540 | } else {
541 | $path .= "\n\t\t\t\t".(($i - 1) * $stepX + 50).' '.$HEIGHT.' 50 '.$HEIGHT."\n\t\t\t\t";
542 | }
543 | if ($opacity > 0.8) {
544 | $stroke = $tmp;
545 | }
546 | $return .= $path.'" class="graph-fill" fill="'.$stroke.'" fill-opacity="'.$opacity.'"/>'."\n";
547 | }
548 | //Display line
549 | $return .= $path.$pathLine;
550 |
551 | if($circles == true) {
552 | $return .= "\t".'';
553 | $return .= $c;
554 | $return .= "\n\t".''."\n";
555 | }
556 | return $return;
557 | }
558 |
559 | /**
560 | * To draw histograms
561 | * @param $data array Unidimensionnal array
562 | * @param $height integer Height of grid
563 | * @param $HEIGHT integer Height of grid + title + padding top
564 | * @param $stepX integer Unit of x-axis
565 | * @param $unitY integer Unit of y-axis
566 | * @param $lenght integer Size of data array
567 | * @param $min integer Minimum value of data
568 | * @param $max integer Maximum value of data
569 | * @param $options array Options
570 | * @return string Path of lines (with options)
571 | *
572 | * @author Cyril MAGUIRE
573 | */
574 | protected function __drawBar($data,$height,$HEIGHT,$stepX,$unitY,$lenght,$min,$max,$options) {
575 | $return = '';
576 |
577 | extract($options);
578 |
579 | $this->colors[] = $options['stroke'];
580 |
581 | //Bar
582 | $bar = '';
583 | $i = 0;
584 | $c = '';
585 | $t = '';
586 | foreach ($data as $label => $value) {
587 |
588 | if ($min <=0) {
589 | $V = ($value-$min);
590 | } else {
591 | $V = $value;
592 | }
593 |
594 | //Tooltips and circles
595 | if($tooltips == true) {
596 | $c .= "\n\t\t".'';
597 | }
598 |
599 | $stepY = $V*$unitY;
600 |
601 | //$min>=0
602 | $coordonnees1 = 'x="'.($i * $stepX + 50).'" y="'.($HEIGHT + $paddingTop - $unitY*$V).'"';
603 | //On recule d'un demi pas pour que la valeur de x soit au milieu de la barre de diagramme
604 | $coordonnees2 = 'x="'.($i * $stepX + 50 - $stepX/2).'" y="'.($HEIGHT + $paddingTop - $stepY).'"';
605 | //$min<0
606 | $coordonnees3 = 'x="'.($i * $stepX + 50 - $stepX/2).'" y="'.($HEIGHT + $paddingTop - $unitY*$V).'"';
607 | //$min<0 et $value<0
608 | $coordonnees4 = 'x="'.($i * $stepX + 50 - $stepX/2).'" y="'.($HEIGHT + $paddingTop - $unitY*$V + $stepY).'"';
609 | $coordonnees5 = 'x="'.($i * $stepX + 50).'" y="'.($HEIGHT + $paddingTop - $unitY*$V + $stepY).'"';
610 | //$min>=0 et $value == $max
611 | $coordonnees6 = 'x="'.($i * $stepX + 50).'" y="'.($paddingTop + $titleHeight + ($height - $stepY) + $paddingTop).'"';
612 | //$value == 0
613 | $coordonnees7 = 'x="50" y="'.($HEIGHT + $paddingTop + $unitY*$min).'"';
614 | if ($value == 0) {
615 | $stepY = 1;
616 | }
617 | //Diagramme
618 | //On est sur la première valeur, on divise la largeur de la barre en deux
619 | if ($i == 0) {
620 | if ($value == $max) {
621 | $bar .= "\n\t".'';
622 |
623 | $c .= "\n\t\t\t".'';
624 |
625 | } else {
626 | if ($min>=0) {
627 | $bar .= "\n\t".'';
628 |
629 | $c .= "\n\t\t\t".'';
630 |
631 | } else {
632 | if ($value == $min) {
633 | $bar .= "\n\t".'';
634 | } else {
635 | if ($value == 0) {
636 | $bar .= "\n\t".'';
637 | } else {
638 | $bar .= "\n\t".'';
639 | }
640 | }
641 |
642 | $c .= "\n\t\t\t".'';
643 |
644 | }
645 |
646 | }
647 | } else {
648 | if ($value == $max) {
649 | if ($min>=0) {
650 | //Si on n'est pas sur la dernière valeur
651 | if ($i != $lenght-1) {
652 | $bar .= "\n\t".'';
653 |
654 | } else {
655 | $bar .= "\n\t".'';
656 | }
657 | $c .= "\n\t\t\t".'';
658 | } else {
659 | if ($value >= 0) {
660 | //Si on n'est pas sur la dernière valeur
661 | if ($i != $lenght-1) {
662 | $bar .= "\n\t".'';
663 | } else {
664 | $bar .= "\n\t".'';
665 | }
666 | } else {
667 | //Si on n'est pas sur la dernière valeur
668 | if ($i != $lenght-1) {
669 | $bar .= "\n\t".'';
670 | } else {
671 | $bar .= "\n\t".'';
672 | }
673 | }
674 |
675 | $c .= "\n\t\t\t".'';
676 |
677 | }
678 | }else {
679 | if ($min>=0) {
680 | //Si on n'est pas sur la dernière valeur
681 | if ($i != $lenght-1) {
682 | $bar .= "\n\t".'';
683 | } else {
684 | $bar .= "\n\t".'';
685 | }
686 |
687 | $c .= "\n\t\t\t".'';
688 |
689 | } else {
690 | if ($value >= 0) {
691 | //Si on n'est pas sur la dernière valeur
692 | if ($i != $lenght-1) {
693 | $bar .= "\n\t".'';
694 | } else {
695 | $bar .= "\n\t".'';
696 | }
697 | } else {
698 | //Si on n'est pas sur la dernière valeur
699 | if ($i != $lenght-1) {
700 | $bar .= "\n\t".'';
701 | } else {
702 | $bar .= "\n\t".'';
703 | }
704 | }
705 |
706 | $c .= "\n\t\t\t".'';
707 |
708 | }
709 | }
710 | }
711 | $i++;
712 | //End of tooltips
713 | if($tooltips == true) {
714 | $c .= ''.(is_array($tooltipLegend) ? $tooltipLegend[$i] : $tooltipLegend).$value.''."\n\t\t".'';
715 | }
716 | }
717 |
718 | //Filling
719 | if ($filled === true) {
720 | if ($opacity == 1) {
721 | $opacity = '1" stroke="#424242';
722 | }
723 | $barFilled = str_replace(' class="graph-bar" stroke="'.$stroke.'" fill="#fff" fill-opacity="0"/>', ' class="graph-bar" fill="'.$stroke.'" fill-opacity="'.$opacity.'"/>',$bar);
724 | $return .= $barFilled;
725 | }
726 |
727 | $return .= $bar;
728 |
729 | if($circles == true) {
730 | $return .= "\n\t".'';
731 | $return .= $c;
732 | $return .= "\n\t".''."\n";
733 | }
734 | return $return;
735 | }
736 |
737 | /**
738 | * To draw pie diagrams
739 | * @param $data array Unidimensionnal array
740 | * @param $options array Options
741 | * @return string Path of lines (with options)
742 | *
743 | * @author Cyril MAGUIRE
744 | */
745 | protected function __drawDisk($data,$options=array(),$id=false) {
746 |
747 | $options = array_merge($this->options,$options);
748 |
749 | extract($options);
750 |
751 | if (is_string($legends)) {
752 | $mainLegend = $legends;
753 | } else {
754 | $mainLegend = null;
755 | }
756 | if (is_string($stroke)) {
757 | $mainStroke = $stroke;
758 | } else {
759 | $mainStroke = $this->__genColor();
760 | }
761 |
762 | $lenght = count($data);
763 | $max = max($data);
764 |
765 | $total = 0;
766 | foreach ($data as $label => $value) {
767 | if ($value < 0) {$value = 0;}
768 | $total += $value;
769 | }
770 | $deg = array();
771 | $i = 0;
772 | foreach ($data as $label => $value) {
773 |
774 | if ($value < 0) {$value = 0;}
775 | if ($total == 0) {
776 | $deg[] = array(
777 | 'pourcent' => 0,
778 | 'val' => $value,
779 | 'label' => $label,
780 | 'tooltipLegend' => (is_array($tooltipLegend) && isset($tooltipLegend[$i])) ? $tooltipLegend[$i] : (isset($tooltipLegend) && is_string($tooltipLegend) ? $tooltipLegend : ''),
781 | 'stroke' => (is_array($stroke) && isset($stroke[$i]))? $stroke[$i] : $this->__genColor(),
782 | );
783 | } else {
784 | $deg[] = array(
785 | 'pourcent' => round(((($value * 100)/$total)/100),2),
786 | 'val' => $value,
787 | 'label' => $label,
788 | 'tooltipLegend' => (is_array($tooltipLegend) && isset($tooltipLegend[$i])) ? $tooltipLegend[$i] : (isset($tooltipLegend) && is_string($tooltipLegend) ? $tooltipLegend : ''),
789 | 'stroke' => (is_array($stroke) && isset($stroke[$i]) ) ? $stroke[$i] : $this->__genColor(),
790 | );
791 | }
792 | $i++;
793 | }
794 | if (isset($legends)) {
795 | if (!is_array($legends) && !empty($legends) && !is_bool($legends)) {
796 | $Legends = array();
797 | for ($l=0;$l<$lenght;$l++) {
798 | $Legends[$l] = array(
799 | 'label' => $deg[$l]['label'].' : '.$deg[$l]['val'],
800 | 'stroke' => $deg[$l]['stroke']
801 | );
802 | }
803 | $legends = $Legends;
804 | unset($Legends);
805 | } elseif (empty($legends)) {
806 | $notDisplayLegends = true;
807 | } elseif (is_bool($legends)) {
808 | $legends = array();
809 | }
810 | foreach ($deg as $k => $v) {
811 | if (!isset($legends[$k]) || !is_array($legends[$k])) {
812 | $legends[$k] = array(
813 | 'label' => $v['label'].' : '.$v['val'],
814 | 'stroke' => $v['stroke']
815 | );
816 | }
817 | }
818 | }
819 | $deg = array_reverse($deg);
820 |
821 | $heightLegends = 0;
822 | if (isset($legends) && !empty($legends)) {
823 | $heightLegends = count($legends)*30+2*$paddingTop+80;
824 | } else {
825 | $heightLegends = 2*$paddingTop+100;
826 | }
827 |
828 | $this->colors[] = $options['stroke'];
829 |
830 | $originX = (2*$radius+400)/2;
831 | $originY = 10+$titleHeight+2*$paddingTop;
832 |
833 |
834 | //Size of canevas will be bigger than grid size to display legends
835 | $return = "\n".'