Interaktive Datenvisualisierung: Animieren der viewBox

Avatar of Sarah Drasner
Sarah Drasner am

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

Die Art und Weise, wie eine Datenvisualisierung zur Laufzeit auf Ihrer Seite angeordnet wird, ist wirkungsvoll im Hinblick auf die Vermittlung von Informationen. In der Vergangenheit haben wir darüber gesprochen, wie wir dies nutzen können, um Informationen ein- und auszublenden für responsives Design. Bei der Arbeit mit SVG können wir dies tun, indem wir die viewBox wie eine Kamera verwenden, um die relevanten Informationen auf der Seite zu isolieren und dem Betrachter hervorzuheben. Es gibt so viele Anwendungsmöglichkeiten für diese Technik. Wir werden uns eine neue Art ansehen, dynamisch damit zu arbeiten, damit der Prozessor die schwere Arbeit für uns erledigt.

Bevor wir uns mit dem Animieren der viewBox beschäftigen, sollten wir behandeln, was die viewBox in SVG *ist*. Ich werde hier nur die Grundlagen behandeln, aber wenn Sie tiefer eintauchen möchten, gibt es einige großartige Artikel, die Ihnen dabei helfen.

Die viewBox fungiert als *Fenster*, durch das Sie in Ihr SVG blicken. Sie wird mit 4 Koordinatenwerten definiert: min-x, min-y, width und height. Wenn Sie die Grafik unten sehen, können Sie die vollständige Zeichnung sehen.

Der schwarze Kasten darum definiert die viewBox. Wenn Sie mit Illustrator vertraut sind, ist dies das "Artboard". Sie können das Artboard in Illustrator ändern, indem Sie zu Datei > Dokument einrichten > Artboards bearbeiten gehen. Sie können dann Ihr Bild zur Laufzeit zuschneiden und den sichtbaren Bereich ändern. Wenn Sie wissen, dass Ihre Grafik genau die Größe Ihrer gewünschten viewBox hat, können Sie dies schnell mit Objekt > Artboards > An Gestaltungsgrenzen anpassen tun.

Siehe den Pen mit der vollständigen viewBox von Sarah Drasner (@sdras) auf CodePen.

Wenn wir die viewBox gleich lassen und die Breite und Höhe des SVG ändern können.

Siehe den Pen mit der vollständigen viewBox von Sarah Drasner (@sdras) auf CodePen.

Man kann sich das ein wenig so vorstellen, als ob das SVG-DOM sich entlang eines Rasters selbst abbildet. Dieses Raster kann schrumpfen und wachsen, aber das Seitenverhältnis des Rasters bleibt konstant. Hier haben wir das SVG bei 0 min der x-Achse des Rasters und 0 min der y-Achse abgebildet. Die Breite dehnt sich um 384,5 und die Höhe um ungefähr 250.

Wenn wir diese Häuser zusammen gruppieren, können wir auch sehen, wo sie liegen.

Wir können den gesamten sichtbaren Bereich auf nur die Häuser zuschneiden, indem wir die viewBox auf "215 160 42.2 20" ändern.

Um die viewBox-Koordinaten für diese Gruppe zu ermitteln, könnten wir einige Messungen durchführen, manuell bearbeiten, aber das ist ziemlich mühsam und da die viewBox skalierbar ist, wird es schwierig. Zum Glück gibt es eine native Methode, die wir verwenden können, namens getBBox(). Diese gibt den Begrenzungsrahmen zum Zeitpunkt des Aufrufs der Methode zurück und schließt Strichstärken, Masken oder Filtereffekte aus. Sie gibt zu diesem Zeitpunkt ein SVGRect-Objekt zurück (auch wenn es noch nicht gerendert wurde).

Das Coole an dem SVGRect-Objekt ist, dass es vier Werte zurückgibt: x-min, y-min, width und height. Kommt Ihnen das ein wenig bekannt vor, hm?

Das ist wirklich praktisch für uns, denn um die viewBox dynamisch zu aktualisieren, müssen wir nur die Werte aus dem Objekt als unseren neuen viewBox-String speichern, also var newView = "" + s.x + " " + s.y + " " + s.width + " " + s.height;.

Dann können wir den neuen viewBox-String als viewBox-Attribut auf dem SVG setzen: foo.setAttribute("viewBox", newView);.

Siehe den Pen mit der vollständigen viewBox von Sarah Drasner (@sdras) auf CodePen.

Jetzt geht es zur Sache.

Um zu den neuen viewBox-Werten zu animieren, haben wir mehrere Optionen, alle unter Verwendung von JavaScript (vorerst).

  • Wir können requestAnimationFrame mit einem Polyfill verwenden, um den Wert unserer Koordinaten über die Zeit zu aktualisieren.
  • Wir können den attr-Plugin von GreenSock (bereits im typischen Standard-Bibliothek von TweenMax enthalten) verwenden, um ihn zu animieren.

Das Coole an GreenSock ist, dass es jede beliebige Zweizahl animieren kann, daher ist es ein sehr nützliches Werkzeug dafür. Ich werde GreenSock im folgenden Beispiel verwenden, da ich noch eine Reihe anderer Dinge animieren möchte und eine schnelle, endliche Kontrolle über meine Easing-Werte wünsche. Aber beide Methoden funktionieren gut.

Eine kurze Anmerkung: SVGRect gibt immer ein Rechteck zurück, auch wenn das betreffende Element keines ist, und es gibt keine Diagonalen, auch nicht, wenn es transformiert ist. Hier ist eine kurze Demo einiger rotierender Formen mit einer Kontur, damit Sie sehen, was ich meine.

Siehe den Pen Was mit der Bounding Box passiert, wenn ein SVG-Element rotiert wird von Sarah Drasner (@sdras) auf CodePen.

Im folgenden Beispiel habe ich eine Karte, und wenn der Benutzer mit ihr interagiert, möchte ich mehr Informationen über das von ihm ausgewählte Land geben.

Siehe den Pen Animierte ViewBox-Datenvisualisierung von Sarah Drasner (@sdras) auf CodePen.

Ich habe eine wiederholte Animation für die Hotspots. Ich verwende auch einige einfache data-Attribute auf den Elementen selbst, damit ich diese Informationen speichern und verwenden kann, um sie zu animieren. Eine konsistente Benennung ist hier wichtig – so steuere ich, welches Land erweitert wird und welche Details angezeigt werden.

<g data-name="usa" class="hotspot">
  <circle id="dot2" cx="221" cy="249" r="2.4" fill="url(#radial-gradient)"/>
  <circle id="dot1" cx="221" cy="249" r="2.4" fill="url(#radial-gradient)"/>
  <circle id="dotmid" cx="221" cy="249" r="2.3" fill="#45c6db"/>
</g>

Ich habe auch etwas zusätzlichen Abstand zu den Hotspot-Elementen hinzugefügt, damit ihr Klickziel für mobile Geräte und unsere Finger groß genug ist.

.hotspot {
  cursor: pointer;
  /* make the hit targets bigger for mobile */
  padding: 20px;
}

Ich kann dann eine Funktion schreiben, die beim Klicken das data-Attribut übergibt und die viewBox basierend auf der Form des Landes aktualisiert. Ich habe der Breite 200 hinzugefügt, um Platz für den Text neben dem Land zu schaffen.

// interaction
function zoomIn(country) {
// zooming in part
var currentCountry = document.getElementById(country),
    s = currentCountry.getBBox(),
    newView = "" + s.x + " " + s.y + " " + (s.width + 200) + " " + s.height,
    group1 = [".text-" + country, ".x-out"],
    tl = new TimelineMax();
  
    tl.add("zIn");
    tl.fromTo(map, 1.5, {
      attr: { viewBox: "0 0 1795.2 875.1"}
    }, {
      attr: { viewBox: newView }
    }, "zIn");
    tl.to(".text-" + country, 0.1, {
      display: "block"
    }, "zIn");
    tl.fromTo(group2, 0.25, {
      opacity: 1
    }, {
      opacity: 0,
      ease: Circ.easeIn
    }, "zIn");
    tl.fromTo(currentCountry, 0.35, {
      opacity: 0
    }, {
      opacity: 1,
      ease: Circ.easeOut
    }, "zIn+=0.5");
    tl.fromTo(group1, 0.5, {
      opacity: 0
    }, {
      opacity: 0.65,
      ease: Sine.easeOut
    }, "zIn+=1");
}

$(".hotspot").on("click", function() {
  var area = this.getAttribute('data-name');
  $(".x-out").attr("data-info", area);
  zoomIn(area);
});

Wenn ich meinen Code super schlank haben wollte, hätte ich die Timeline in eine Funktion packen und sie einfach umkehren können, wenn jemand auf das X klickt. Aber als ich das versuchte, war die Animation einfach ein wenig schlampiger, als mir gefiel, also habe ich eine neue Funktion erstellt, um das Timing etwas zu verfeinern. Ich hätte auch tl.to anstelle von fromTo verwenden können, aber ich habe festgestellt, dass beim Neustart von Animationen das Anbieten eines Anfangswerts in fromTo hilft, es etwas zu stabilisieren (besonders wenn man nicht weiß, wer den Code vielleicht aktualisiert).

ViewBox in CSS?

Jake Archibald hat vorgeschlagen, die viewBox als CSS-Eigenschaft zu fördern, was ich sehr unterstütze. Wenn Sie es auch unterstützen möchten, fügen Sie entweder einen Kommentar mit technischen Rückmeldungen hinzu oder geben Sie einem der vorhandenen Kommentare einen Daumen hoch (um eine Überfüllung des Hauptthreads zu vermeiden). Eine CSS-Eigenschaft zur Steuerung der viewBox wäre wunderbar, da wir einfach Media Queries und Animationen anwenden könnten, vielleicht sogar Layout-Trigger und Repaints für solche Updates reduzieren.

Eine weitere Demo: Eine geführte Infografik

Für zusätzlichen Spaß habe ich ein kleines Flussdiagramm erstellt, um zu zeigen, wie diese Technik zur Führung von Benutzern verwendet werden kann. Dieses spezielle Diagramm führt Benutzer zur Auswahl des richtigen Bildformats für die jeweilige Aufgabe.

Siehe den Pen Animiertes Flussdiagramm 3 von Sarah Drasner (@sdras) auf CodePen.

Animationswarnung: Es ist potenziell schwindelerregend, also spielen Sie nicht damit, wenn Sie eine vestibuläre Störung haben. Wenn ich dies auf einer Produktionsseite einbetten würde, könnte ich einen Schalter zum Ausschalten der Animation oder eine Fallback-Option zu einem vereinfachten Fragebogen anbieten.

Weitere Erkundungen

Es gibt auch andere, die sich mit der Idee der Animation der viewBox beschäftigen. Louis Hoebregts schrieb einen großartigen Beitrag dazu, und David Bachmann Johannesson hat diesen schlanken und fantastischen Pen erstellt, unter anderem.

Haben Sie andere gesehen? Verlinken Sie uns in den Kommentaren.