Frage zu Kreisdiagrammen im Wiki-Artikel „Balken-_und_Kreisdiagramme“
Robert B.
- frage zum wiki
- svg
Hallo Forum,
in o.g. genannten Abschnitt des Artikels ist ein Beispiel für ein Kreisdiagramm gegeben, das mir nicht einleuchtet:
<svg class="chart" width="420" height="150" aria-labelledby="chartinfo" >
<desc id="chartinfo">Ein Diagramm unserer Ernte</desc>
<defs>
</defs>
<svg class="pie" width="200" height="200" viewBox="-100 -100 200 200" style="transform: rotate(-0.25turn)">
<circle id="background" r="50" />
<g class="slice" tabindex="0">
<path d="M 1 0 A 1 1 0 0 1 0.8 0.59 L 0 0 Z" />
<text x="45" y="9.5">4 apples</text>
</g>
</svg>
</svg>
Da ist erst einmal ein svg
in einem svg
– was soll das denn?
Weiterhin:
Viele Grüße
Robert
Servus!
Hallo Forum,
in o.g. genannten Abschnitt des Artikels ist ein Beispiel für ein Kreisdiagramm gegeben, das mir nicht einleuchtet:
<svg class="chart" width="420" height="150" aria-labelledby="chartinfo" > <desc id="chartinfo">Ein Diagramm unserer Ernte</desc> <defs> </defs> <svg class="pie" width="200" height="200" viewBox="-100 -100 200 200" style="transform: rotate(-0.25turn)"> <circle id="background" r="50" /> <g class="slice" tabindex="0"> <path d="M 1 0 A 1 1 0 0 1 0.8 0.59 L 0 0 Z" /> <text x="45" y="9.5">4 apples</text> </g> </svg> </svg>
Da ist erst einmal ein
svg
in einemsvg
– was soll das denn?Weiterhin:
- Wenn ich das richtig sehe, muss ich die Koordinaten für den Kreisbogen/die weiteren Tortenstücke aus den Anteilen (prozentual zur Basis 360° bzw. 2π) berechnen.
- Die Vorschau des Kreisdiagramm-Beispiels „existiert nicht“.
Ja, das ist leider steckengeblieben.
Da wollte ich mal einen kompletten Diagramm-Generator bauen, bei dem man dann das fertig generierte SVG als Grafik oder als eigene Datei (siehe deinen Osterei-Generator) ausgeben kann.
Ich hoffe, dass ich Weihnachten dazu komme. :-(
Herzliche Grüße
Matthias Scharwies
Moin Matthias,
Ja, das ist leider steckengeblieben.
ich bin ja nicht ohne eine Idee über die Seite gestolpert … 😉 Mir würde es fürs erste Verständnis reichen, wenn ich Antworten auf die folgenden Frage finde:
Da ist erst einmal ein
svg
in einemsvg
– was soll das denn?Weiterhin:
- Wenn ich das richtig sehe, muss ich die Koordinaten für den Kreisbogen/die weiteren Tortenstücke aus den Anteilen (prozentual zur Basis 360° bzw. 2π) berechnen.
Daraus ergäben sich Teile meiner Idee, die dann hierher zurückfließen könnten:
Da wollte ich mal einen kompletten Diagramm-Generator bauen, bei dem man dann das fertig generierte SVG als Grafik oder als eigene Datei (siehe deinen Osterei-Generator) ausgeben kann.
Viele Grüße
Robert
Servus!
Moin Matthias,
Ja, das ist leider steckengeblieben.
ich bin ja nicht ohne eine Idee über die Seite gestolpert … 😉 Mir würde es fürs erste Verständnis reichen, wenn ich Antworten auf die folgenden Frage finde:
Da ist erst einmal ein
svg
in einemsvg
– was soll das denn?Weiterhin:
Das war mein Versuch, den Kreis, der skaliert werden muss, mit einer viewbox passend zu skalieren. Bei g geht das nicht.
Irgendwie muss man sowohl den path mit dem Segment und dann den text (class="slice" ist blöd; besser wäre wohl label?) in das Diagramm kriegen.
- Wenn ich das richtig sehe, muss ich die Koordinaten für den Kreisbogen/die weiteren Tortenstücke aus den Anteilen (prozentual zur Basis 360° bzw. 2π) berechnen.
Ja, genau! Und da war für mich die Frage,
wie ich den Bogen berechne (meine Idee Umfang des Kreises berechnen, dort dann den Prozentwert des Anteils dazu und dann den Endpunkt des Bogens draufsetzen.
ob ich alle Kreissegmente oben zeichne und dann entsprechend der bisherigen Anteile rotiere
Daraus ergäben sich Teile meiner Idee, die dann hierher zurückfließen könnten:
Da wollte ich mal einen kompletten Diagramm-Generator bauen, bei dem man dann das fertig generierte SVG als Grafik oder als eigene Datei (siehe deinen Osterei-Generator) ausgeben kann.
vielen Dank im Voraus!!!
Herzliche Grüße
Matthias Scharwies
--
Hallo Matthias,
da steckt einiges an Hirnschmalz drin.
Ein konischer Gradient ist am allereinfachsten und braucht vor allem überhaupt kein SVG, hat aber zwei Nachteile:
Das Thema Randlinie kann man beheben, indem man das Diagramm zweimal übereinander zeichnet. Einmal mit der Farbe für die Randlinien, darüber dann, etwas kleiner, die Farbe für die Füllflächen.
Die dasharray-Idee ist ebenfalls clever, aber mathematisch obskur. Man braucht den Radius des Kreises und muss daraus die Länge des Umfangs berechnen. Dann muss man die Pie-Größen darauf umrechnen und kennt nun die Längen für den sichtbaren Strichanteil. Die unsichtbare Strichlänge kann man einfach auf den Umfang setzen. Hier erhebt das Wiki den gleichen Einwand wie bei conic-gradient: Keine individuellen Randfarben möglich. Lösung wie dort: zwei Pies übereinander. Die Platzierung der Slices würde ich mit dashoffset machen, das ist am einfachsten.
Malt man die Pies explizit mit path d="A...", hat man aber, was die Randfarben angeht, das gleiche Problem. Ein Stroke umrundet nämlich die ganze Slice, nicht nur den Außenrand. Entweder muss man mit dasharray nachhelfen, oder man zeichnet die Randlinie separat. Das ist also auch kein "it just works". Bei Arcs kommt hinzu, dass man die Koordinaten berechnen muss. Zumindest die des Arc-Endpunkts. Und man muss aufpassen, ob das Slice mehr als 50% des Pie einnimmt, weil man dann nämlich das large-arc Flag im A Befehl setzen muss. Um den Arc richtig zu positionieren, sollte man das tun, was Du überlegt hast: um den benötigten Winkel rotieren. Was bei Pies blöd ist: Man kann das d-Attribut nicht per CSS zusammenrechnen. Man kann es zwar im CSS festlegen, aber var() wird darin nicht verstanden. Man muss also per JS die jeweils benötigte d-Eigenschaft komplett zusammenstoppeln.
Ich stell noch was in meinen User-Space im Wiki
Rolf
Moin Matthias,
- Wenn ich das richtig sehe, muss ich die Koordinaten für den Kreisbogen/die weiteren Tortenstücke aus den Anteilen (prozentual zur Basis 360° bzw. 2π) berechnen.
Ja, genau! Und da war für mich die Frage,
- wie ich den Bogen berechne (meine Idee Umfang des Kreises berechnen, dort dann den Prozentwert des Anteils dazu und dann den Endpunkt des Bogens draufsetzen.
- ob ich alle Kreissegmente oben zeichne und dann entsprechend der bisherigen Anteile rotiere
Also nach meiner kurzen Feierabend-Spielerei (und -Geometrie) ist es gar nicht so kompliziert:
circle
definieren (entsprechende viewBox
mit negativen x- und y-Koordinaten nötig).Das habe ich in https://www.robertbienert.de/self/torte.html einmal ausprobiert es macht fürs Erste einen guten Eindruck. Mit einer Beispieleingabe wie
#39f .5
#93f .3
#f39 .25
#f93 1
#3f9 .4
#9f3 .5
kann man auch gleich einmal hübsche Farbpaletten ausprobieren.
Neben dem Hinweis von @Rolf B mit dem large-arc sweep für Winkel > 180° habe ich auch eine Sonderbehandlung für Winkel = 180° enthalten, weil das ein einfacher Halbkreis ist, für den ich kein Dreieck der rechten Ecke berechnen könnte.
Ich denke, dass wir darauf aufbauen können 😀
Knifflig wird es noch beim Beschriften der Tortenstücke, weil die Beschriftung ja nicht mit-rotiert werden sollte.
Viele Grüße
Robert
Moin Matthias,
nachdem ich vergeblich versucht habe den Beispielcode funktionsfähig zu bekommen,
<svg class="chart" width="420" height="150" aria-labelledby="chartinfo" > <desc id="chartinfo">Ein Diagramm unserer Ernte</desc> <defs> </defs> <svg class="pie" width="200" height="200" viewBox="-100 -100 200 200" style="transform: rotate(-0.25turn)"> <circle id="background" r="50" /> <g class="slice" tabindex="0"> <path d="M 1 0 A 1 1 0 0 1 0.8 0.59 L 0 0 Z" /> <text x="45" y="9.5">4 apples</text> </g> </svg> </svg>
habe ich jetzt mit einem anderen Ansatz angefangen und schon einmal das Funktionsprinzip visualisiert. Die Frage ist, wie ich jetzt weitermache, ob ich z.B. meinen Ansatz als separaten Absatz in den Wiki-Artikel einfüge oder erst einmal im Benutzer-Namensraum arbeite.
Viele Grüße
Robert
Servus!
Moin Matthias,
nachdem ich vergeblich versucht habe den Beispielcode funktionsfähig zu bekommen,
<svg class="chart" width="420" height="150" aria-labelledby="chartinfo" > <desc id="chartinfo">Ein Diagramm unserer Ernte</desc> <defs> </defs> <svg class="pie" width="200" height="200" viewBox="-100 -100 200 200" style="transform: rotate(-0.25turn)"> <circle id="background" r="50" /> <g class="slice" tabindex="0"> <path d="M 1 0 A 1 1 0 0 1 0.8 0.59 L 0 0 Z" /> <text x="45" y="9.5">4 apples</text> </g> </svg> </svg>
Ja, das schien in dem einen Tutorial so einfach zu sein, brachte mich aber auch zur Verzeiflung.
habe ich jetzt mit einem anderen Ansatz angefangen und schon einmal das Funktionsprinzip visualisiert.
Super! Vielen Dank!
Die Frage ist, wie ich jetzt weitermache, ob ich z.B. meinen Ansatz als separaten Absatz in den Wiki-Artikel einfüge oder erst einmal im Benutzer-Namensraum arbeite.
Theoretisch im Benutzernamnesraum. Da haben wir Aktiven aber das Problem, dass wir einige unserer Projekte "gleich weitermachen" wollten, und dnan nach Jahren auf 90%-fertige Tutorials stoßen, die wir selbst vergessen hatten.
Meine persönlichee Meinung: Das was du jetzt hast ist besser als der Ist-Stand! Setz es doch in den Artikel und signalisiere mit einem `{{ToDo|--~~~~}} , dass du ab dieser Stelle noch am Arbeiten bist.
Herzliche Grüße
Matthias Scharwies
Moin Matthias,
Meine persönlichee Meinung: Das was du jetzt hast ist besser als der Ist-Stand! Setz es doch in den Artikel und signalisiere mit einem `{{ToDo|--~~~~}} , dass du ab dieser Stelle noch am Arbeiten bist.
jetzt fehlen nur noch schöne Formeln und dann bin ich mit dem, was ich für unbedingt nötig halte, soweit fertig.
Für einen Diagramm-Editor (oder dynamisches Erzeugen von Diagrammen z.B. mit Webservice-Daten) hat @Rolf B noch gute Hinweise geliefert – vielleicht lässt sich das sogar mit dem WebComponents-Ansatz kombinieren.
Viele Grüße
Robert
Hallo Robert,
jetzt fehlen nur noch schöne Formeln und dann bin ich mit dem, was ich für unbedingt nötig halte, soweit fertig.
Super, vielen Dank!
Ich hatte immer nur die Anzeige in den letzten Änderungen gesehen! Heute abend schau ich mir das ganz in Ruhe mal an!
Für einen Diagramm-Editor (oder dynamisches Erzeugen von Diagrammen z.B. mit Webservice-Daten) hat @Rolf B noch gute Hinweise geliefert – vielleicht lässt sich das sogar mit dem WebComponents-Ansatz kombinieren.
Ja, wobei eben der SVG-Download auch attraktiv klingt!
Herzliche Grüße
Matthias Scharwies
--
Servus!
Hallo Robert,
jetzt fehlen nur noch schöne Formeln und dann bin ich mit dem, was ich für unbedingt nötig halte, soweit fertig.
Super, vielen Dank!
Ja, das sieht alles super aus!
Evtl. könnte man bei :hover anstatt der hellblauen Füllung die Randline verstärken und die Füllfarbe leuchten lassen.
Hier würde das Element scheinbar vergrößert, weil die Randlinie die Füllfarbe verwendet. Den Schlagschatten müsste man optimieren.
.segment:hover path,
.segment:focus path {
filter: brightness(1.15) drop-shadow(2px 2px 4px black);
stroke-width:2;
stroke: context-fill;
}
Für einen Diagramm-Editor (oder dynamisches Erzeugen von Diagrammen z.B. mit Webservice-Daten) hat @Rolf B noch gute Hinweise geliefert – vielleicht lässt sich das sogar mit dem WebComponents-Ansatz kombinieren.
Ja, wobei eben der SVG-Download auch attraktiv klingt!
Wenn Du Lust hast, kannst du die unteren ToDos überarbeiten oder löschen.
Nochmals vielen Dank!
Herzliche Grüße
Matthias Scharwies
Moin Matthias,
Evtl. könnte man bei :hover anstatt der hellblauen Füllung die Randline verstärken und die Füllfarbe leuchten lassen.
Hier würde das Element scheinbar vergrößert, weil die Randlinie die Füllfarbe verwendet. Den Schlagschatten müsste man optimieren.
.segment:hover path, .segment:focus path { filter: brightness(1.15) drop-shadow(2px 2px 4px black); stroke-width:2; stroke: context-fill; }
Sieh mal einer an, stroke: context-fill
wird mittlerweile mindestens vom Firefox unterstützt. Vor einem Jahr war das noch nicht der Fall.
Für einen Diagramm-Editor (oder dynamisches Erzeugen von Diagrammen z.B. mit Webservice-Daten) hat @Rolf B noch gute Hinweise geliefert – vielleicht lässt sich das sogar mit dem WebComponents-Ansatz kombinieren.
Ja, wobei eben der SVG-Download auch attraktiv klingt!
Kann man die HTML-Serialisierung aus dem Shadow-DOM kopieren oder gibt es keinen Zugriff darauf?
Wenn Du Lust hast, kannst du die unteren ToDos überarbeiten oder löschen.
Das schaue ich mir in nächster Zeit an, ja.
Viele Grüße
Robert
Servus!
Moin Matthias,
Evtl. könnte man bei :hover anstatt der hellblauen Füllung die Randline verstärken und die Füllfarbe leuchten lassen.
Hier würde das Element scheinbar vergrößert, weil die Randlinie die Füllfarbe verwendet. Den Schlagschatten müsste man optimieren.
.segment:hover path, .segment:focus path { filter: brightness(1.15) drop-shadow(2px 2px 4px black); stroke-width:2; stroke: context-fill; }
Sieh mal einer an,
stroke: context-fill
wird mittlerweile mindestens vom Firefox unterstützt. Vor einem Jahr war das noch nicht der Fall.
Sorry, ich glaub' ich bin der letzte Firefox-Nutzer.
https://caniuse.com/mdn-svg_attributes_presentation_fill_context-fill
2.69% klingen nicht gut! 😟
Für einen Diagramm-Editor (oder dynamisches Erzeugen von Diagrammen z.B. mit Webservice-Daten) hat @Rolf B noch gute Hinweise geliefert – vielleicht lässt sich das sogar mit dem WebComponents-Ansatz kombinieren.
Ja, wobei eben der SVG-Download auch attraktiv klingt!
Kann man die HTML-Serialisierung aus dem Shadow-DOM kopieren oder gibt es keinen Zugriff darauf?
Wenn Du Lust hast, kannst du die unteren ToDos überarbeiten oder löschen.
Das schaue ich mir in nächster Zeit an, ja.
Vielen Dank im Voraus!
Herzliche Grüße
Matthias Scharwies
Hallo Robert B.,
ich habe mir deinen Code angeschaut und bin vom Ergebnis erfreut, aber im Detail leicht unzufrieden.
Woher bin ich so „schlau“? Ich habe mir den Code eine gute Stunde lang angeschaut und dran hin- und hergebaut. Das Ergebnis ist auch nicht unbedingt so wie ich es gern hätte, darum behalte ich es lieber noch für mich…
Das Problem mit dem Rand bei :hover ist eins, für das ich aber auch noch keine Idee habe. SVG kennt keine z-order und die Hinweise, die man im Netz finden, besagen, dass man das zu hovernde Element im DOM nach hinten setzen müsse, damit es in der z-order vorne ist. Das braucht dann natürlich mousemove Handler und noch mehr JavaScript. Was ich eigentlich doof finde. Vielleicht bekommt man das Chart ja so hin, dass die Ränder sich nicht überlagern. Leider kennt SVG auch keine Option "male den Rand an der Innenseite", d.h. da muss man dann die Punkte für den Rand separat berechnen.
Rolf
Moin Rolf,
ich hätte vielleicht dazu schreiben sollen (fehlendes javascript
-Schlagwort im Forum ist vermutlich zu implizit), dass ich erst einmal nicht vorhabe etwas Interaktives ins Wiki zu schreiben, sondern nur eine Anleitung, wie man Tortendiagramme mit SVG konstruieren kann, also
Das ganze JavaScript-Geraffel war nur für mich zum Ausprobieren, ob meine Mathematik funktioniert. 😉
Viele Grüße
Robert
Moin Rolf,
- reduce funktioniert auch ohne Sonderbehandlung für length=1. Verwende den dritten Parameter (Anfangswert) und übergib 0.
da ich die Summe über eine Array-Komponente bilde, muss der Aufruf von Array.prototype.reduce
entsprechend aussehen und auch den passenden Startwert als Array haben:
// Beispiel:
const vals = [['red', 1], ['green', 2], ['black', 5]];
// allgemeine Summe für leeres Array
// oder mit beliebiger Anzahl an Elementen:
const sum = vals.reduce((p,c) => [0, p[1] + c[1]], [0,0])[1];
Viele Grüße
Robert
Hallo Robert B.,
da ich die Summe über eine Array-Komponente bilde, muss der Aufruf von Array.prototype.reduce entsprechend aussehen und auch den passenden Startwert als Array haben:
Nö. Ein Array als Summenelement durchzuschleifen ist kein muss. Es steht nirgends geschrieben, dass der Typ des Summenparameters zwingend vom gleichen Typ wie die Array-Einträge sein muss. Du hast den reduce-Eintrag im Wiki doch gelesen (weiß ich, weil Du daran etwas verbessert hast). Guck mal:
// Beispiel:
const vals = [['red', 1], ['green', 2], ['black', 5]];
// allgemeine Summe für leeres Array
// oder mit beliebiger Anzahl an Elementen:
const sum = vals.reduce((sum,value) => sum+value[1], 0);
// ▲▲▲
Gibt man reduce keinen dritten Parameter, dann bildet das erste Arrayelement ("red") den initialen sum-Wert, und die reduce-Schleife beginnt erst beim zweiten Array-Element damit, den Callback aufzurufen.
Wenn ich nur Zahlen im Array habe und der Callback für das erste Arrayelement nichts anderes tun würde, als dieses Element als neue Summe zurückzugeben, ist das unproblematisch.
Wenn man aber komplexere Dinge tut, ist der dritte Parameter hilfreich. Er tut zweierlei:
Ich habe das Beispiel aus diesem Thread mal ins Wiki übertragen.
Rolf
Moin,
Da wollte ich mal einen kompletten Diagramm-Generator bauen, bei dem man dann das fertig generierte SVG als Grafik oder als eigene Datei (siehe deinen Osterei-Generator) ausgeben kann.
nachdem ich jetzt für ein anderes Projekt wieder damit zu tun hatte (und ich einen Ansatz dafür habe), würde ich das Thema Diagramm-Generator wieder aufgreifen – und zwar (auch) so, dass ein kopierbares HTML+SVG-Snippet entsteht, damit man nicht via DOM-Inspektor der Browser-Tools das Outer HTML kopieren muss, sondern es bequem aus dem Web UI möglich ist.
Viele Grüße
Robert
Servus!
Moin,
Da wollte ich mal einen kompletten Diagramm-Generator bauen, bei dem man dann das fertig generierte SVG als Grafik oder als eigene Datei (siehe deinen Osterei-Generator) ausgeben kann.
nachdem ich jetzt für ein anderes Projekt wieder damit zu tun hatte (und ich einen Ansatz dafür habe), würde ich das Thema Diagramm-Generator wieder aufgreifen – und zwar (auch) so, dass ein kopierbares HTML+SVG-Snippet entsteht, damit man nicht via DOM-Inspektor der Browser-Tools das Outer HTML kopieren muss, sondern es bequem aus dem Web UI möglich ist.
Super, vielen Dank im Voraus!
Herzliche Grüße
Matthias Scharwies