[HTML / CSS / PHP] Wie Tortengrafik erstellen

Cyperfriend

Der ohne Avatar
Registriert
14 Juli 2013
Beiträge
1.123
Ich würde gerne eine Tortengrafik erstellen. Als Grundlage dienen Zahlen aus einer Datenbank.

Jetzt habe ich aber leider überhaupt keine Idee, wie man das anstellen kann. Kann mir jemand behilflich sein oder ist das für Anfänger ohnehin viel zu kompliziert? Auf JavaScript oder fremde Bibliotheken will ich (wie immer) verzichten. Als Grafikstil reicht mir was einfaches, also Draufsicht, platt. Dafür aber mit verschiedenen Farben.

Der Code muss am Ende so sein, dass automatisch erkannt wird, wie viele Stücke die Torte haben muss. Als erstes will ich die eingetragenen Bildschirme aus der Datenbank auslesen. Dabei sollen Hersteller, Modell und Größe beachtet werden.
 
Zuletzt bearbeitet:
Entweder du erstellst die Grafik im Backend, nutzt JavaScript, oder du hast Pech.

Ansonsten:



Es gibt keinen Grund nicht auf Java Script oder Bibliotheken zu setzen, dafür sind sie da.
 
Muss es ein Tortendiagramm sein? Soll eine echte Grafik erzeugt werden?

Einfacher wäre ein Balkendiagramm.


[src=css]<style type="text/css">
#bar
{
height: 10px;
border:1px solid #000;
width: 1000px;
}
.fraction
{
float: left;
height: 10px;
border:1px solid #000;
}
.fraction:last-child
{
float: none;
}
</style>[/src]

[src=php]<?php

$barwidth=1000px;
$values = array('Peter' => 7, 'Max' => 18, 'Hans' => 26, 'Karl' => 14.5, 'Otto' => 8, 'Benedikt' => 0, 'Petra' => 3.5, 'Melanie' => 6);

# Berechne Summe als 100% Referenz
$sum=0;
foreach ($values as $value)
{
$sum += $value;
}

// Summe: 83

# /0 vermeiden
if ($sum==0)
{
$sum=1;
}

# Berechne %-Anteil des jeweiligen Wertes an Summe
$fractions=array();
foreach($values as $value){
$fractions[] = $value / $sum;
}


# Erzeuge Ausgabe
echo '<div id="bar">';
foreach ($fractions as $fraction)
{
$fractionwidth = $fraction * $barwidth/$sum;
echo '<div class="fraction" style="width:'.$fractionwidth.'px;"></div>';
}
echo '</div>';
?>[/src]

Das ist jetzt nur schnell runter geschrieben um dir eine Richtung zu zeigen, sicherlich könnte und sollte man das noch optimieren und schöner ginge es sicherlich auch und mit Sicherheit habe ich sogar den ein oder anderen Fehler drin, so wie ich mich kenne. ;)
 
Auch Tortendiagramme lassen sich relativ leicht erzeugen:



Hier mal ganz quick and dirty:

[src=php]$values = array('Peter' => 7, 'Max' => 18, 'Hans' => 26, 'Karl' => 14.5, 'Otto' => 8, 'Benedikt' => 5, 'Petra' => 3.5, 'Melanie' => 6);
$r = 1000;

$image = imagecreatetruecolor($r, $r / 2);
$white = imagecolorallocate($image, 255, 255, 255);

$start = 0;
foreach($values as $name => $value){
$text = $name . ': '. $value;
$color = imagecolorallocate($image, rand(100, 150), 20, rand(150, 255));
$end = $start + ($value / array_sum($values)) * 360;
$x = $r / 2 + cos(deg2rad(($start + $end) / 2)) * $r / 2 * 0.9 - strlen($text) * 5;
$y = $r / 4 + sin(deg2rad(($start + $end) / 2)) * $r / 4 * 0.9 - 10;
imagefilledarc($image, $r / 2, $r / 4, $r, $r / 2, $start, $end, $color, IMG_ARC_PIE);
imagestring($image, 5, $x, $y, $text, $white);
$start = $end;
}

header('Content-type: image/png');
imagepng($image);
imagedestroy($image);[/src]

Aber auch ich würde Dir dazu raten, eine fertige Bibliothek zu benutzen, wie Lemondrops es schon vorgeschlagen hat.
 
Ja, ist natürlich nur nicht so intuitiv verständlich für einen Anfänger, oder meinst du nicht? :D
Wäre aber mal interessant, warum keine Bibliothek verwendet werden darf/soll.
 
  • Thread Starter Thread Starter
  • #6
Danke epiphora. Der Code funktioniert, aber ich verstehe das leider nicht. Was mich auch etwas stört ist, dass die Farben ähnlich sind und immer wechseln. Kann man das so modifizieren, dass die Farben immer gleich sind, also der größte Anteil immer grün, der Zweitgrößte immer blau und so weiter. Alternativ wäre es natürlich nett, wenn man die Farbwerte festlegen könnte, also beispielsweise, dass Peter immer grün hat, Max immer blau und so weiter. Dann bräuchte es aber die Komponente "unbekannt", wenn für etwas kein Farbwert definiert wurde und darunter dann zusammengefasst wird. (Beispielsweise für Petra und Melanie wurde kein Farbwert definiert und fällt daher unter "Unbekannt")

Würdest du mir bitte eine Vorlage basteln, die mit einer Datenbank arbeitet. Ich weis, ich sollte das mit den Arrays hinbekommen, aber Arrays und ich, das ist so eine Sache, vor allem wenn es dynamisch sein soll.
 
Du musst lediglich diesen Teil hier:

[src=php]
$color = imagecolorallocate($image, rand(100, 150), 20, rand(150, 255));
[/src]

abändern mit den festen Farben deiner Wahl.
Da kannst du oben in deinem array zb noch die Farbe angeben und weiter unten, bzw. hier in diesem Posting über dieser Zeile die Werte dann in dem foreach-Block wieder ausgeben und anwenden.
Die Farben in diesem Script werden in einem bestimmten Farbbereich immer per Zufall ausgegeben.

Versuch dich doch einfach mal ein wenig selbst. Hilfe bekommst du hier genug, wenn du nicht mehr weiter weisst. Wenn man sich alles machen lässt, lernt man mal genau nix.
Hier: kannst du sämtliche Funktionen nachschlagen, welche du im Script findest.

epi: Du erinnerst mich an meine Frau. Die sagt auch immer, ich soll die Schubladen schliessen, wenn ich was rausgenommen hab. :D Das ist mir nur gerade eingefallen bei deinem imagedestroy. Wenn du per Header die Bilddatei direkt ausgibst, ist das Script vmtl auch recht bald beendet (zumindest erfolgt wohl keine Ausgabe mehr) und die Sache erledigt sich von selbst. Und jetzt sage ich dir wie meiner Frau:

Nie mehr machen als nötig. :D :p
 
Zuletzt bearbeitet:
Wenn man es so macht, kann man die Dinger gleich in Photoshop anlegen, interaktiv ist da eh nix.
 
Wenn man es so macht, kann man die Dinger gleich in Photoshop anlegen, interaktiv ist da eh nix.

Warum genau sollte das nicht interaktiv sein? Nur weil du eine fixe Anzahl an möglichen Farben hast, heißt das nicht, dass die Daten nicht dynamisch sein können.
Zufällige Farben finde ich auch nicht praktisch.
 
Chart.js ist ~4,5kb groß, wenn es minfied und gzipt ist und kann gecacht werden. Damit kann ich beliebig viele, schöne Charts machen und immer neue per Ajax nachladen, dafür brauche ich nur ein paar Bytes Json. Es ist absoluter Unsinn solche Grafiken auf dem Server dynamisch zu erzeugen und aus zu liefern.

Es ist nicht Interaktiv, weil es eine Grafik ist, eine Bilddatei. Da hat der User keinen Einfluss drauf.
 
Zuletzt bearbeitet:
Chart.js ist ~4,5kb groß, wenn es minfied und gzipt ist und kann gecacht werden. Damit kann ich beliebig viele, schöne Charts machen und immer neue per Ajax nachladen, dafür brauche ich nur ein paar Bytes Json. Es ist absoluter Unsinn solche Grafiken auf dem Server dynamisch zu erzeugen und aus zu liefern.

Es ist nicht Interaktiv, weil es eine Grafik ist, eine Bilddatei. Da hat der User keinen Einfluss drauf.

Ach ja? Du kannst selbst mit HTML auf Grafiken "arbeiten", erst recht mit JavaScript. Wenn du willst, kannst du die Nutzerinteraktion auch an den Server leiten und da Grafiken manipulieren und die Ergebnisse wieder zurück bekommen.
Interaktiv sagt nichts darüber aus, <wo> eine Handlung passiert, sondern dass es mindestens 2 Kommunikationspartner gibt und diese sich miteinander kommunizieren können, Aktion und Reaktion existieren. Das ist durchaus gegeben. Bspw: Nutzer gibt in ein statisches Formular Daten ein, sendet diese an den Server, der Server erzeugt die Grafik und schickt diese zurück zum Nutzer.
Aber nicht mal der letzte Schritt muss für "interaktiv" getan werden. Eine Interaktion kann auch ohne direktes Feedback passieren. Bspw. Nutzer besuchen eine Seite, der Server speichert Seitenbesuche, der Administrator bekommt eine Grafik zu statistischen Werten bezüglich der Nutzerzugriffe angezeigt. Die Richtung ist hier Besucher => Server => Betreiber und selbst das ist eine Art der Interaktion.

Nur weil eine Grafik pseudo-Statisch ist, tatsächlich statisch ist sie nämlich nur dann, wenn eine statische Ressource angesprochen wird, was bei einer dynamisch erzeugten Grafik schon nicht der Fall ist, heißt das nicht, dass die Gesamtkreation nicht interaktiv sein muss.
 
Es ist absoluter Unsinn solche Grafiken auf dem Server dynamisch zu erzeugen und aus zu liefern.
Zumindest als Fallback scheint mir das sehr sinnvoll, da man andernfalls unnötigerweise eine JavaScript-Abhängigkeit schafft. Natürlich könnte man, sofern JS aktiviert ist, die statische Grafik durch eine per Chart.js generierte ersetzen. Allerdings sehe ich darin kaum einen Mehrwert, wenn die Grafik nicht in regelmässigen Zeitabständen per AJaX aktualisiert werden soll.

Es ist nicht Interaktiv, weil es eine Grafik ist, eine Bilddatei. Da hat der User keinen Einfluss drauf.
Das war hier allerdings auch nicht das Ziel - es sollte bloss dynamisch eine Tortengrafik aus Daten erstellt werden, welche aus einer Datenbank stammen. Dies leistet das von epiphora gepostete Skript.
 
Allerdings sehe ich darin kaum einen Mehrwert, wenn die Grafik nicht in regelmässigen Zeitabständen per AJaX aktualisiert werden soll.

Ein kleinere Dateigröße und weniger Requests sind ein riesiger Mehrwert. Als Fallback gibt es Text, den Text können auch Screenreader gut lesen. Wer kein Javascript aktiviert hat, hat einfach Pech, man braucht einer Minderheit nicht hinterher laufen. Wer Javascript deaktiviert, ist sich auch bewusst, worauf er sich einlässt.
 
Das kann man so oder so sehen.
Beim Client generiert bedeutet:
A. Der Serverbetreiber hat u.U. weniger Traffic.
B. Der Serverbetreiber muss mehr Daten herausgeben, als er eventuell möchte.
C. Die Gesamtrechenlast steigt. Ein mal auf dem Server generiert ist 1x Rechenlast, bei Client (Session) generiert heißt, bei jedem Aufruf neu generiert.

Zu den libs wurde ja gesagt, dass keine erwünscht sind bzw. JavaScript prinzipiell nicht. Wenn wir mal davon ausgehen, dass dann auch hoffentlich kein Flash, Silverlight und andere Krebsgeschwüre erwünscht sind, bleibt nicht mehr viel übrig.
 
Alle Daten die man braucht um die Chart zu erstellen, sind die Daten, die man sowieso in der Grafik abbildet. Die Rechenzeit die für solche Charts gebraucht wird ist marginal, vor allem im Verhältnis zu dem, was es braucht um eine Webseite zu rendern. Außerdem braucht es auch Zeit Bilddaten zu laden und Rechenzeit um diese abzubilden, das gibt's auch nicht umsonst.

Es gibt keinen Grund so etwas auf dem Server in hässlich zu machen bzw. könnte man das ruhig mal mit dem TS diskutieren.
 
Ein kleinere Dateigröße und weniger Requests sind ein riesiger Mehrwert.
Die kleinere Grösse der zu übertragenden wird aber durch das zusätzlich herunterzuladende Skript und den zusätzlichen Request eben dafür teilweise kompensiert. Die Grafik könnte man, wenn man sie mit indizierter Palette (PNG-8 oder GIF) erstellt oder gar SVG verwendet, noch einmal deutlich besser komprimieren, mutmasslich sogar auf weniger als die 4.5 KiB deines Skripts (die auch nur unter der Annahme erreicht werden, dass der Client gzip-Übertragung unterstützt). Allerdings ist die Datenmenge in diesem Fall ohnehin vernachlässigbar gering (< 10 KiB), selbst für langsame Internetzugänge, so dass ich darin weder für die eine noch für die andere Lösung einen Mehrwert erkennen kann und auch keinen Optimierungsbedarf sehe. Wenn ein Bild mit einigen 100 KiB Grösse übertragen werden müsste, die Grafik regelmässig per AJaX aktualisiert werden sollte, oder viele verschiedene Charts auf einer Seite ausgegeben werden sollten, könnte ich das nachvollziehen.

Als Fallback gibt es Text, den Text können auch Screenreader gut lesen. Wer kein Javascript aktiviert hat, hat einfach Pech, man braucht einer Minderheit nicht hinterher laufen. Wer Javascript deaktiviert, ist sich auch bewusst, worauf er sich einlässt.
Gegen Text als zusätzliches Fallback (z.B. in Form eines sinnvollen alt- oder longdesc-Attributs für das img-Element) spricht sicherlich nichts. Und während ich dir zustimme, dass man JavaScript durchaus sehr sinnvoll nutzen kann, bedeutet das nicht, dass man blind davon ausgehen kann, dass JS auf jedem Client verfügbar ist und man es daher gedankenlos einsetzen sollte, wenn alternative Lösungen existieren, welche ohne JavaScript auskommen. Wenn man denn JS einsetzen möchte, muss man für adäquate Fallbacks sorgen, und wenn dann die JS-Nutzung gegenüber den Fallbacks keinen oder nur einen sehr geringen Mehrwert bietet, kann man auch darauf verzichten.
 
Nein, das muss nicht zwangsweise sein. Aus der Grafik heraus kannst du genaue Werte eher schwer bis gar nicht ablesen. übermittelst du sie, hast du sie aber übertragen. (Nur ein Beispiels.)

Ob das zum Schluss schön oder hässlich aussieht, hängt nicht damit zusammen, ob du serverseitig oder clientseitig arbeitest, sondern im Zweifelsfall daran wie gut oder schön es programmiert wurde. Denn zumindest sollten turing-vollständige Programmiersprachen gleich mächtig sein. ;)
Klar, Frameworks helfen dir eine "schöne" Darstellung zu erreichen, so dass du möglichst wenig Input leisten musst. Da ist es aber unerheblich, ob du ein serverseitiges Framework verwendest oder ein clientseitiges.

Bezüglich deiner Zeitrechnung:

Serverseitig:
* Erstellen auf dem Server (x RE)
* Senden (y1 RE pro Client)
* Darstellen (z RE pro Client)
Clientseitig:
* Senden (y2 RE pro Client)
* Erstellen beim Client (x RE pro Client)
* Darstellen (z RE pro Client)

Die Darstellung selbst findet in beiden Fällen gleich oft und mit gleichem load (z Recheneinheiten) statt, die Berechnung der darzustellenden Grafik (x Recheneinheiten) allerdings im Fall serverseitig lediglich einmal im Gegensatz zum Fall clientseitig. Du könntest dich bestenfalls fragen, ob du durch das Senden der "Blankodaten" dermaßen viel Traffic (y1 vs y2) sparst, dass sich die clientseitige Berechnung der Grafik lohnt. Dafür sollte für realistische n gelten: n*x + n*y2 <= x + n*y1, wenn ich jetzt nicht falsch liege.. Wobei n die Anzahl der Clients (bzw. genauer gesagt der Aufrufe) ist und caching ist natürlich nicht beachtet.

Natürlich kann das u.U. Sinn ergeben, wenn ich für zig tausende Clients Grafiken berechnen müsste, werde ich das höchst wahrscheinlich auch auf den Client abwälzen, dann spare ich mir die Rechenzeit und brauche einen weniger potenten Server.

Abgesehen davon sehe ich es nicht als Argument "die Leute, die JavaScript deaktiviert haben, wissen, worauf sie sich einlassen". Sag das mal im B2B-Bereich zu einem Geschäftskunden. Dann kannst du von einem ausgehen, wer auf seine zahlende Kundschaft nicht zugehen möchte, der weiß ebenfalls, worauf er sich einlässt und da hast du in aller Regel keine braven Schäfchen, die dir nachlaufen, egal, wie sehr du sie schlägst, das macht der treue Mediamarktkunde, aber in der B2B Welt triffst du das eher selten an.
 
Ich denke wir haben alle Recht, je nachdem wovon man aus geht.

Wenn jeder User die gleichen Charts sieht, dann lohnt es sich die Grafiken auf dem Server zu generieren und zu cachen.
Wenn jeder User individuelle Chats sieht, dann lohnt es sich die Charts im Frontend zu erzeugen.

Es ist einfach eine Frage der Last die man dem Server aufbürden möchte. Jede Menge Wegwerf-Charts auf dem Server generieren ist keine gute Idee.
 
Zurück
Oben