Diagramme mit SVG erstellen

Avatar of Robin Rendle
Robin Rendle am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

In meinem ersten Beitrag über die Erstellung von Diagrammen habe ich Methoden untersucht, die ausschließlich auf CSS basieren. Ich habe argumentiert, dass dies in den meisten Fällen nicht die beste Option ist; es gibt einfach zu viele knifflige Design- und Entwicklungshürden zu überwinden. Generell ist es am besten, Diagramme mit einer Kombination aus SVG, JavaScript und CSS zu erstellen.

Warum nicht canvas?

Es gibt viele andere Möglichkeiten, ein Diagramm für das Web zu erstellen, am bekanntesten ist die Verwendung des canvas-Elements. Sara Soueidan schlägt jedoch vor, auch diese Methode zu vermeiden.

HTML5 Canvas kann auch zur Erstellung solcher Visualisierungen verwendet werden, aber der Inhalt der Canvas ist nicht Teil des DOM und somit nicht für Screenreader zugänglich. Sie müssten einen sekundären Inhalt zwischen den öffnenden und schließenden <canvas></canvas>-Tags erstellen, der als Fallback und zugänglicher Inhalt dient. Sie müssen auch zusätzliche Maßnahmen ergreifen, um den Inhalt und die Interaktivität zwischen den Inhalten der Canvas und dem Fallback abzubilden, damit Screenreader wissen, mit welchem Element interagiert wird. Eine HTML5 Canvas würde also doppelt so viel Wartungsaufwand erfordern. […] Mit SVG erhalten Sie Semantik und Barrierefreiheit sowie Interaktivität mit JavaScript sofort.

Es gibt jedoch Alternativen zu diesem eigenständigen canvas-Ansatz. Zum Beispiel hat Filament Group ein jQuery-Plugin namens Visualize entwickelt, das Daten aus einem table-Element abruft und dann ein canvas-Diagramm erstellt. Diese Praxis ist sehr sinnvoll, auch wenn das Element allein nicht gut für die Erstellung von Graphen geeignet ist.

Warum SVG?

Das SVG-Bildformat ist nicht nur für Icons oder einfache Bilder gedacht. Es hat auch Vorteile, die sich auf die Erstellung von Diagrammen anwenden lassen. In unserem Kompendium von SVG haben wir die allgemeinen Vorteile des Formats wie folgt beschrieben:

  • Kleine Dateigrößen, die gut komprimiert werden
  • Skaliert auf jede Größe ohne Verlust an Klarheit (außer bei sehr kleinen Größen)
  • Sieht auf Retina-Displays großartig aus
  • Designkontrolle wie Interaktivität und Filter

Wir können dies um zwei weitere wichtige Punkte ergänzen, die für Diagramme nützlich sind:

  • SVGs sind für Screenreader zugänglich (mit etwas Aufwand)
  • Es gibt viele SVG-basierte Diagramm-Frameworks, die helfen können

Legen wir los. Was ist der einfachste Ansatz, um ein Diagramm mit SVG zu erstellen?

Diagramme mit

Ein Diagramm mit SVG zu erstellen, kann so einfach sein wie es in Illustrator oder Ihrer bevorzugten Vektor-Design-App zu entwerfen, es als SVG zu exportieren und es dann direkt in den Markup mit einem <img>-Tag einzufügen.

<img src="chart.svg" alt="Hopefully you can impart equally useful alternate content here.">

Das ist großartig, weil es gut aussieht und gut skaliert. Wir verlieren jedoch die meisten Vorteile von Inline-SVG, wie Barrierefreiheit und Interaktivität. Abgesehen von Alt-Texten werden unsere Daten nicht von Screenreadern vorgelesen und die Datenpunkte in den Diagrammen selbst können nicht per Maus, Touch oder Tastatureingabe mit ihnen interagieren.

Diese Probleme deuten darauf hin, dass wir eine andere SVG-Einbettungstechnik verwenden sollten, wenn wir so viel Kontrolle wie möglich darüber gewinnen wollen. Was passiert zum Beispiel, wenn wir an einem Projekt wie Death from Above arbeiten würden, bei dem die interaktive Natur der Graphen uns sehr hilft, die Daten zu verstehen?

A gif showing the interface of the Death from Above website

Um das Beste aus SVG herauszuholen, müssen wir all diesen Code nehmen und ihn direkt in unseren Markup einfügen. Auf diese Weise können wir den Graphen mit CSS gestalten, die Interaktivität mit JavaScript steuern und alle Vorteile von Inline-SVG für die Barrierefreiheit nutzen.

(Ähnliche Vorteile könnten wir mit SVG-Einbettungen über <object> oder <iframe> erzielen, aber das Konzept ist so ähnlich, dass wir mit Inline-SVG weitermachen.)

Balkendiagramme

Jede Spalte in unserem Diagramm wird innerhalb eines <g>-Elements (in SVG-Sprache ist dies nur eine Gruppe zusammengehöriger Elemente) enthalten sein, in jedem davon platzieren wir ein <rect>-Element, das die Form der Spalte definiert, und ein <text>-Element, das es uns ermöglicht, die Zahl auf dem Bildschirm anzuzeigen. Hier ist ein fertiges Beispiel.

Wir können diese <rect>- und <text>-Elemente mit den Standard-x/y-Koordinaten positionieren, wie hier gezeigt:

<svg class="chart" width="420" height="150" aria-labelledby="title desc" role="img">
  <title id="title">A bar chart showing information</title>
  <desc id="desc">4 apples; 8 bananas; 15 kiwis; 16 oranges; 23 lemons</desc>
  <g class="bar">
    <rect width="40" height="19"></rect>
    <text x="45" y="9.5" dy=".35em">4 apples</text>
  </g>
  <g class="bar">
    <rect width="80" height="19" y="20"></rect>
    <text x="85" y="28" dy=".35em">8 bananas</text>
  </g>
  <g class="bar">
    <rect width="150" height="19" y="40"></rect>
    <text x="150" y="48" dy=".35em">15 kiwis</text>
  </g>
  <g class="bar">
    <rect width="160" height="19" y="60"></rect>
    <text x="161" y="68" dy=".35em">16 oranges</text>
  </g>
  <g class="bar">
    <rect width="230" height="19" y="80"></rect>
    <text x="235" y="88" dy=".35em">23 lemons</text>
  </g>
</svg>

Beachten Sie, dass Sie mit der Maus über die Elemente fahren können, um die Farbe des Balkens und die Textfarbe zu ändern? Das ist mit der CSS-Eigenschaft fill möglich.

.bar {
  fill: red; /* changes the background */
  height: 21px;
  transition: fill .3s ease;
  cursor: pointer;
  font-family: Helvetica, sans-serif;
}
.bar text {
  color: black;
}
.bar:hover,
.bar:focus {
  fill: black;
}
.bar:hover text,
.bar:focus text {
  fill: red;
}

Juhu für einfache, interaktive SVGs!

Hier gibt es jedoch ein Problem: Das Tabbieren durch das Diagramm funktioniert nicht (weil Browser das focusable-Attribut noch nicht unterstützen). Léonie Watson hat Barrierefreiheitstipps für SVG, die vorschlagen, <a xlink:href="#">-Links für die Fokussierbarkeit zu verwenden – aber was, wenn der fokussierbare Bereich nicht wirklich ein Link ist?

Wir werden uns damit bald in kommenden Artikeln genauer befassen.

Sparklines

Da Sparklines im Grunde winzige Balkendiagramme sind, können wir viel von dem gleichen Code wie zuvor verwenden, um dieses Beispiel zu erstellen.

Diesmal können wir, um jedes g-Element nebeneinander auszurichten, eine Inline-CSS-transform-Eigenschaft verwenden (es ist wahrscheinlich am besten, bei den Standard-x- und y-Koordinaten zu bleiben, aber dies beweist nur, dass es möglich ist). Dann ändern wir das height-Attribut des rect-Elements, um die Daten korrekt anzuzeigen, und verschieben jedes Element von oben nach unten mit der y-Koordinate. Dies sollte jeden Balken am unteren Rand der Sparkline ausrichten. Hier ist ein abgekürztes Codebeispiel.

<g class="bar" transform="translate(0,0)">
  <rect height="10" y="10" width="3"></rect>
</g>
<g class="bar" transform="translate(3,0)">
  <rect height="6" y="14" width="3"></rect>
</g>

Liniendiagramme

Um die Datenpunkte eines Liniendiagramms zu markieren, können wir das polyline-Element und das points-Attribut verwenden.

<svg viewBox="0 0 500 100" class="chart">
  <polyline
     fill="none"
     stroke="#0074d9"
     stroke-width="3"
     points="
       0,120
       20,60
       40,80
       60,20"/>
</svg>

0,120 in diesem Beispiel bedeutet 0 von links und 120 von oben auf der SVG-Leinwand. Und sobald wir unsere Liste von Datenpunkten fertig haben, können wir die Breite der Linie mit stroke-width und die Farbe dieser Linie mit stroke definieren.

Aber das stylt nur die Daten – was ist mit diesen wichtigen Linien, die jedem helfen, die Punkte selbst zu entschlüsseln? Was ist mit den Achsen?

Erstellung der Achsen und Beschriftungen

Roemer Vlasveld hat ein großartiges Tutorial über die Entwicklung von Grafiken mit SVG erstellt und dokumentiert einige interessante Eigenschaften, die uns helfen werden, jede Achse eines Graphen zu beschriften und zu gestalten. Wir nehmen eine vereinfachte Version seiner Arbeit für das folgende Beispiel.

<svg class="graph">
  <g class="grid x-grid">
    <line x1="90" x2="90" y1="5" y2="371"></line>
  </g>
  <g class="grid y-grid">
    <line x1="90" x2="705" y1="370" y2="370"></line>
  </g>
</svg>

Jede g wird verwendet, um die horizontalen und vertikalen Linien zu erstellen, und in Kombination mit den korrekt positionierten Textbeschriftungen ergibt dies unsere grundlegenden Stile und den Markup für ein Streudiagramm, nur ohne die Daten.

Nachdem wir jeden Punkt unserer Daten als eine Reihe von circles innerhalb eines weiteren g-Elements hinzugefügt haben, können wir sehen, wie dies als Streudiagramm aussehen könnte.

Kreisdiagramme

Wir haben Leas Verou Artikel über Kreisdiagramme bereits ein paar Mal erwähnt, da er eine ausgezeichnete Einführung ist, um uns den Einstieg zu erleichtern. Ich werde ihre Technik hier nicht im Detail wiederholen, obwohl ich denke, es wäre interessant zu sehen, wie wir diese SVG-Kreisdiagramme interaktiv gestalten könnten. Hier ist ein fertiges Beispiel, das Ihnen eine Vorstellung davon gibt, wohin wir gehen.

Wenn einer der Knöpfe über dem Kreisdiagramm angeklickt wird, aktualisiert sich das Diagramm mit dem Wert, der in einem JavaScript-Objekt gespeichert ist. Diese Methode hat möglicherweise Probleme mit der Barrierefreiheit, aber worauf ich mich konzentrieren möchte, ist die interaktive Kombination von JavaScript und SVG.

Zuerst der Markup:

<figure>
  <figcaption>
    Percentage of world population by continent
  </figcaption>
  
  <div class="buttons"></div>

  <svg width="100" height="100" class="chart">
    <circle r="25" cx="50" cy="50" class="pie"/>
  </svg>
</figure>

Dann können wir unsere Bevölkerungsdaten wie folgt einrichten:

var continents = {
  asia: 60,
  northAmerica : 5,
  southAmerica: 9,
  oceania: 1,
  africa: 15,
  europe: 12
};

Was wir hier tun wollen, ist, das leere .buttons-Div mit einer Reihe von Buttons zu füllen, die beim Klicken die stroke-dasharray-Eigenschaft des circle-SVG-Elements ändern. Wir können diese Buttons wie folgt erstellen:

var buttons = document.querySelector('.buttons');

for(property in continents) {
  var newEl = document.createElement('button');
  newEl.innerText = property;
  newEl.setAttribute('data-name', property);
  buttons.appendChild(newEl);
}

Als Nächstes müssen wir diese Prozentsätze korrigieren, da asia: 60 in unserem continents-Objekt *60 von 100* bedeutet und nicht *60 vom Umfang unseres Kreises*. Wir können eine Funktion erstellen, um dies für uns zu beheben.

var total = 158; 

var numberFixer = function(num){
  var result = ((num * total) / 100);
  return result;
}

Von dort aus können wir jedem dieser Buttons einen Event-Listener hinzufügen und eine neue Funktion namens setPieChart() erstellen, die den Wert von stroke-dasharray ändert, indem sie das data-name-Attribut jedes Buttons überprüft und den entsprechenden Kontinent in unserem Objekt findet.

buttons.addEventListener('click', function(e){
  if(e.target != e.currentTarget) {
    var el = e.target,
        name = el.getAttribute('data-name');
    setPieChart(name);
    setActiveClass(el);
  }
  e.stopPropagation();
});

var setPieChart = function(name) {
  var number = continents[name],
      fixedNumber = numberFixer(number),
      result = fixedNumber + ' ' + total;
  pie.style.strokeDasharray = result;
}

Und sobald wir ein paar Hilfsfunktionen hinzugefügt haben, um den Buttons einen aktiven Stil zu verleihen, haben wir ein voll funktionsfähiges interaktives Kreisdiagramm.

SVG mit CSS und JavaScript manipulieren

Die Animation der Änderungen im vorherigen Beispiel war relativ einfach, wir mussten nur die transition-Eigenschaft in CSS verwenden, wie hier:

circle {
  transition: stroke-dasharray .3s ease;
}

Sobald wir die Eigenschaft mit unserem Skript geändert haben, würde CSS die gesamte Animation für uns durchführen. Aber welche anderen SVG-Eigenschaften und Attribute können mit CSS manipuliert werden?

Nun, eine der Eigenheiten des Stylings von SVG mit CSS ist, dass es nur bestimmte Eigenschaften gibt, die wir steuern können. Wenn wir zum Beispiel die x- oder y-Koordinaten einer g ändern wollen (ohne die CSS-transform-Eigenschaft zu verwenden), müssen wir JavaScript verwenden. Was dies noch seltsamer macht, wenn Sie mit der SVG-Syntax nicht vertraut sind, ist, dass CSS-Eigenschaften bestimmte Elemente beeinflussen, aber nicht andere.

Es gibt eine praktische Liste von Eigenschaften des W3C, die zeigt, welche Eigenschaft welche SVG-Elemente beeinflusst. Stellen Sie also sicher, dass Sie diese Liste doppelt prüfen, wenn Sie nicht sehen, was Sie erwarten, wenn Sie sie gestalten.

SVG von Hand bearbeiten ist keine perfekte Lösung

Mit den anderen Grundformen, einschließlich rect, line und polygon, können wir jede Art von SVG-Diagramm erstellen, die unser Herz begehrt. Die eigentliche Frage ist: Wollen wir das wirklich? Liniendiagramme sind zum Beispiel sicherlich möglich, wenn Sie ein SVG von Hand bearbeiten, aber ich würde es nicht unbedingt empfehlen, da die Syntax etwas komplex ist, besonders wenn Sie etwas wie eine gekrümmte Linie machen wollen.

SVG von Hand zu schreiben kann langsam und frustrierend sein. Selbst für einfache Diagramme dauert es ewig, den Code zu schreiben und jeden Abschnitt visuell zu positionieren. Ähnlich wie bei der reinen CSS-Lösung für Graphen ist Ihre Erfahrung bei der Erstellung eines Diagramms mit SVG von Hand wahrscheinlich schmerzhaft, es sei denn, Sie erstellen etwas sehr Kleines.

Es muss einen besseren Weg geben, oder?

Frameworks zur Rettung!

In einem kommenden Artikel werden wir alle Vorteile (und Probleme) der Verwendung eines Charting-Frameworks diskutieren, um uns die Erstellung zu erleichtern. Wir werden alle beliebten Charting-Frameworks vergleichen und sehen, wie es ist, Daten produktiver und emotional gesünder zu visualisieren.

Weitere Informationen