Array to Graph
Immerwieder passiert es. Man hat Daten die man gerne in einem Diagramm darstellen möchte. Da dies mitunter recht schwer sein kann, habe ich mir meine eigene PHP-Funktion geschrieben, die es mir ermöglicht ein Array direkt mit einem Diagramm zu visualisieren.
Um eine solche Funktion zu Programmieren benötigen wir mehrere Teile.
0. Der Funktionskopf sieht so aus
function arraytograph($data,$w=300,$h=100,$show_keys = true,$label = '')
1. Prüfen ob die übergebenen Werte gefüllt sind. Des Weiteren prüfen wir, welche Achsenbeschriftung angezeigt werden soll. Auch definieren wir hier den Standard Abstand nach oben und unten.
if (!isset($data) || empty($data)) { return FALSE; } if($label == 'value'){ $show_precent = false; $show_number = true; } elseif($label == 'percent'){ $show_precent = true; $show_number = false; } else{ $show_precent = true; $show_number = false; } $pic_border_top = 5; $pic_border_bottom = 5;
2. Die Schlüssel des Arrays holen, um die Achsenbeschriftung zu zeichnen
// getting the keys from array $keys = array_keys($data);
3. Um den Platz für die Achsenbeschriftung zu machen, wird der Längste Schlüssel gesucht. Um genug Platz zu haben, wird die pro Zeichen 6 Pixel gerechnet. Damit die Schrift nicht am Boden “aufsetzt” werden nochmals 12 Pixel hinzugerechnet.
// the keys should be displayed, so add a stripe for displaying the keys // find the longest key. the length of string *6pixel per letter are added to the border bottom if($show_keys){ $max = 0; for($i=0;$i
4. Damit die Möglichkeit besteht, nicht nur die relativen Prozentralen anzeigen zu lassen, suchen wir erneut den längsten String in dem Array. Diesmal jedoch auf die Werte bezogen. Pro Zeichen benutzen wir diesmal 8 Pixel. Wenn Prozentzahlen angezeigt werden sollen, so wird der obere freie Platz um 32 Pixel vergrößert.
// the number should be displayed at the top of the diagramm if($show_number){ $max_num = 0; for($i=0;$i$pic_border_top){ $pic_border_top += $max_num*8; } } if($show_precent){ $pic_border_top += 32; }
5. Um die relative Höhe auszurechnen suchen wir den größten Wert in dem Datenarray und setzten alle anderen Werte in Relation zu diesem Wert.
//Convert the values to percent values $hundredp = max($data); $newarray = array(); foreach ($data as $el) { $newarray[] = intval($el / $hundredp * 100); }
6. Um nun ein Diagramm zu erstellen, nehmen wir die Parameter $w und $h und rufen mit diesen die Funktion imagecreatetruecolor auf. Um später verschiedene Farben benutzen zu können definieren wir uns hier auch gleich ein paar Farben
// let's start with the image-creation $im = imagecreatetruecolor($w, $h); //define colors. $col_background = imagecolorallocate($im, 0, 0, 0); $col_grid = imagecolorallocate($im, 0x53, 0x44, 0x01); $col_bars = imagecolorallocate($im, 0xb7, 0x6b, 0x1a); $col_text = imagecolorallocate($im, 200, 200, 200);
7. Um ein schönes Diagramm erstellen zu können muss es natürlich auch ein Raster geben. Hierzu werden zuerst die horizontalen Linien gezeichnet. Diese werden über die gesamte Breite des Bildes gezeichnet. Um natürlich die horizontalen Linien nur in dem Diagrammbereich zu zeichen, werden hier die Bereiche für die Schlüsselanzeige (unten) und die Werteanzeige(oben) subtrahiert/addiert.
Bei den vertikalen Linien geben wir soviele Linien aus wie es auch Balken geben wird. Auch hier wird nur im Diagrammbereich gezeichnet und der Bereich für die Beschriftungen weggelassen. Mit der Variable $space definieren wir auch gleich die Breite der einzelnen Balken. Da wir natürlich nur begrenzt Platz für die Werte haben, setzen wir diese in eine Relation.
// drawing the grid //horizontal lines for ($i=1; $i<=10; $i++) { imageline($im, 0, $i*(($h-$pic_border_bottom-$pic_border_top)/10)+$pic_border_top, $w, $i*(($h-$pic_border_bottom-$pic_border_top)/10)+$pic_border_top, $col_grid); } //vertical $space = intval($w / count($newarray)); for ($i=1; $i<=count($newarray); $i++) { imageline($im, $i*$space, $pic_border_top, $i*$space, $h-$pic_border_bottom, $col_grid); }
8. Das Zeichnen der Balken
Nun gehen wir das neue Array von vorne beginnend durch und zeichnen jeden Balken.
Da wir wieder nur in dem Diagrammbereich zeichnen wollen, ziehen wir wieder die die $pic_border_top und $pic_border_bottom von den jeweiligen Werten ab. Hier gibt es auch die Möglichkeit die Werte relativ zueinander, also in Prozent, oder in absoluten Zahlen darzustellen. Mit der Variablen $show_percent werden relative Werte ausgegeben mit der Variablen $show_number werden absolute Zahlen angezeigt. Auch gibt es die Möglichkeit die Schlüssel mit anzeigen zu lassen, oder eben nicht
// start drawing the datas for ($i=0; $i
9. Da bisher keine einzige Ausgabe stattfand, können wir nun den Header senden und spezifizieren das es sich um ein png bild handelt. Danach geben wir aus dem erstellten Bild ein PNG aus und zerstören dies auch sogleich. So wird es asugegeben, jedoch nicht in einer datei gespeichert.
//tell the browser that this will be a png image. header("Content-type: image/png"); //finally generate the image; imagepng($im); imagedestroy($im);
So nun haben wir eine fertige Funktion die uns ein Bild ausgibt, sobald wir diese aufrufen.
Da die Funktion mit dem Header arbeitet, können wir diese nicht einfach in den Quellcode einbinden, sondern müssen den Weg über eine neue Datei gehen.
Also erstellen wir uns eine neue Datei die wir als Bild von einer anderen Datei aufrufen können. Sollten keine Daten zum Anzeigen übergeben werden, bricht das Script ab. Ansonsten holt es sich das Datenarray aus der übergebenen URL. Mit serialize lassen sich Arrays in einen String codieren. mit der Funktion unserialize genau das Gegenteil, es wird also aus einem codierten String wieder ein Array geformt. Um die Verarbeitung zu erleichtern, wird nur ein Array übergeben das aus 3 Teilen besteht,
- den anzuzeigenden Daten
- der Höhe
- der Breite
if(!isset($_GET['data'])){ die(); } else{ $data = unserialize(stripslashes($_GET['data'])); $cont = $data['data']; if(isset($data['h'])) $h = $data['h']; if(isset($data['b'])) $b = $data['b']; if(isset($data['keys'])) $keys = $data['keys']; if(isset($data['label'])) $keys = $data['label']; }
Sobald wir dies haben, können wir das ganze Zu einer kompletten Datei zusammensetzen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | <?php function arraytograph($data,$w=300,$h=100,$show_keys = true,$label = ''){ // Check if the array isn't empty if (!isset($data) || empty($data)) { return FALSE; } if($label == 'value'){ $show_precent = false; $show_number = true; } elseif($label == 'percent'){ $show_precent = true; $show_number = false; } else{ $show_precent = false; $show_number = false; } $pic_border_top = 5; $pic_border_bottom = 5; // getting the keys from array $keys = array_keys($data); // the keys should be displayed, so add a stripe for displaying the keys // find the longest key. the length of string *6pixel per letter are added to the border bottom if($show_keys){ $max = 0; for($i=0;$i<count($keys);$i++){ if($max<strlen($keys[$i])) $max = strlen($keys[$i]); } $pic_border_bottom = $max *6+12; } // the number should be displayed at the top of the diagramm if($show_number){ $max_num = 0; for($i=0;$i<count($keys);$i++){ if($max_num<strlen($data[$keys[$i]])) $max_num = strlen($data[$keys[$i]]); } if(($max_num*7)+3>$pic_border_top){ $pic_border_top += $max_num*8; } } if($show_precent){ $pic_border_top += 32; } //Convert the values to percent values $hundredp = max($data); $newarray = array(); foreach ($data as $el) { $newarray[] = intval($el / $hundredp * 100); } // let's start with the image-creation $im = imagecreatetruecolor($w, $h); //define colors. $col_background = imagecolorallocate($im, 0, 0, 0); $col_grid = imagecolorallocate($im, 0x53, 0x44, 0x01); $col_bars = imagecolorallocate($im, 0xb7, 0x6b, 0x1a); $col_text = imagecolorallocate($im, 200, 200, 200); //fill with background color imagefill($im, 0, 0, $col_background); // drawing the grid //horizontal lines for ($i=1; $i<=10; $i++) { imageline($im, 0, $i*(($h-$pic_border_bottom-$pic_border_top)/10)+$pic_border_top, $w, $i*(($h-$pic_border_bottom-$pic_border_top)/10)+$pic_border_top, $col_grid); } //vertical $space = intval($w / count($newarray)); for ($i=1; $i<=count($newarray); $i++) { imageline($im, $i*$space, $pic_border_top, $i*$space, $h-$pic_border_bottom, $col_grid); } // start drawing the datas for ($i=0; $i<count($newarray);$i++){ $x1 = intval($space/2) -1 + $space*$i; $y_bottom = $h-$pic_border_bottom; $y_top = ($h-$pic_border_bottom)-(($newarray[$i])*((($h-$pic_border_bottom)-$pic_border_top)/100)); imagefilledrectangle($im, $x1, $y_bottom, $x1+3, $y_top, $col_bars); if($show_number && !$show_precent){ $number = $data[$keys[$i]]; imagestringup($im, 2, $x1-5, $y_top-10,$number,$col_text); } if($show_precent && !$show_number) imagestringup($im, 2, $x1-5, $y_top-10, $newarray[$i].'%',$col_text); if($show_keys) imagestringup($im, 2, $x1-5, $h-10-(($max-strlen($keys[$i]))*6), $keys[$i],$col_text); } //tell the browser that this will be a png image. header("Content-type: image/png"); //finally generate the image; imagepng($im); imagedestroy($im); } if(!isset($_GET['data'])){ die(); } else{ $data = unserialize(stripslashes($_GET['data'])); $cont = $data['data']; if(isset($data['h'])) $h = $data['h']; if(isset($data['b'])) $b = $data['b']; if(isset($data['keys'])) $keys = $data['keys']; if(isset($data['label'])) $label = $data['label']; } arraytograph($cont,$b,$h,$keys,$label); ?> |
Nun sollte es möglich sein in einer neuen Datei, in der man das Diagramm anzeigen möchte unsere Diagrammdatei als Bildquelle einzubinden. Als zusätzliche Parameter an das Bild übergeben wir die oben genannten 3 Parameter (Daten, Höhe, Breite)
<?php $datas['data'] = array("Stein"=>64,"Lehm"=>128,"Holz"=>256,"Nahrung"=>512,"Menschen"=>1024); $datas['h'] = 200; $datas['b'] = 150; $datas['keys'] = true; $datas['label'] = 'value'; echo "<img src='arraytograph.php?data='.urlencode(serialize ($datas)).'" alt="" /> '; ?>

Nun sehen wir in unserer Datei ein schönes Diagramm
Leicht lassen sich auch andere Möglichkeiten generieren
<?php $datas['data'] = array("Stein"=>64,"Lehm"=>128,"Holz"=>256,"Nahrung"=>512,"Menschen"=>1024); $datas['h'] = 200; $datas['b'] = 150; $datas['keys'] = true; $datas['label'] = 'percent'; echo "<img src='arraytograph.php?data='.urlencode(serialize ($datas)).'" alt="" /> '; ?>

oder auch
<?php $datas['data'] = array("Stein"=>64,"Lehm"=>128,"Holz"=>256,"Nahrung"=>512,"Menschen"=>1024); $datas['h'] = 150; $datas['b'] = 150; $datas['keys'] = true; $datas['label'] = 'value'; echo "<img src='arraytograph.php?data=".urlencode(serialize ($datas))."' > "; ?>

Viel Spass damit ![]()
Erweiterung von Gaming with PHP
Subscribe by Email
Subscribe by Feed