Datenvisualisierung#
Berücksichtigt sehbehinderte Personen bei der Einbeziehung von Datenvisualisierungen. Datentabellen können dabei eine Alternative zu den Datenvisualisierungen für Screen-Reader sein. Berücksichtigt auch die Farbauswahl für farbenblinde Personen. Weitere Emfpehlungen sind:
❌ Verlasst euch nicht auf Farben um die Daten zu erklären
❌ Verwendet keine kontrastarmen Farben
❌ Versteckt keine wichtigen Daten hinter Interaktionen
❌ Überfordert euer Publikum nicht mit zu vielen Informationen
❌ Verlasst euch nicht auf
hover
-Effekte; diese funktionieren nicht auf Mobilgeräten❌ Verzichtet auf Animationen und Scroll-Hijacking, wenn diese nicht wesentlich zur Erklärung der Daten beitragen
✅ Beachtet bereits beim Design die Zugänglichkeit
✅ Beachtet auch kleinere Displays, z.B. bei Mobilgeräten
✅ Verwendet kontrastreiche Farben und Muster
✅ Verwendet Etiketten und Legenden
✅ Übersetzt die Daten in eine klare Sprache
✅ Gebt Kontext an und erklärt die Visualisierung
Siehe auch
Case Study: Implementing Accessible Data Charts for the Khan Academy 2018 Annual Report
How Does This Data Sound? keyboard interaction, sonification etc.
Heather Migliorisi: Accessible SVGs
Carie Fisher: Creating Accessible SVGs
Sarah Higley: Quick Tips for High Contrast Mode
Melanie Richards: CurrentColor SVG in forced colors modes
Val Head: Designing With Reduced Motion For Motion Sensitivities
D3.js#
D3.js ist eine Javascript-Bibliothek zur Datenvisualisierung. Um Datenvisualisierungen zugänglicher zu machen, haben wir ein paar Tipps zusammengestellt:
Um die Farben zu erläutern, könnt ihr eine Legende hinzufügen, z.B. mit:
const legend = chart.append("g").attr("aria-label", "Legend");
Alternativ kann auch ein Titel hinzugefügt werden:
const legend = chart.append("g"); legend.append("text") .text("Legend") .attr("class", "legendTitle");
Nun können wir die Erläuterungen hinzufügen, z.B.:
legend.append("rect") .attr("fill", function(d){return hot(d) }); legend.append("text") .text(">30 °C");
Erläutern der Daten, z.B. für ein Balkendiagramm:
chart.selectAll(".label") .data(data) .enter().append("text") .text(row => row.year);
Optisch sind die Daten jetzt schon sehr viel zugänglicher, aber mit Bedienhilfen werden nun auch die Tage auf der x-Achse erschlossen, und würden z.B. alle vorgelesen werden. Die Zugänglichkeit würde deutlich erhöht werden, wenn die Ausgabe so etwas liefern würde wie Die durchschnittliche Jahrestemperatur betrug 2011 9,6 Grad Celsius.
Hierfür sollten dann nicht zunächst die Daten durchlaufen werden und anschließend die Achsenbeschriftungen sondern jedes Datum mit der zugehörigen Erläuterung:
const ticks = chart.selectAll(".tick") .data(data) .enter().append("g") .attr("class", "tick"); ticks.append("text") .text((data) => data.year); ticks.append("text") .text(row => row.temperature) .attr("class", "label");
Dies gibt folgendes XML aus:
<g> <text>2011</text> <text>9,6 °C</text> </g> …
Bei vielen Achswerten sollten evtl. nicht alle Werte auf der Achse angezeigt werden.
display: none;
odervisibility: hidden
sind jedoch keine Lösung, da die Werte dann z.B. auch nicht vorgelesen würden. Wir können jedoch die Positionierung der Achsenbeschriftungen so verändern, dass sie außerhalb des sichtbaren Rahmens stehen.
Vega#
Vega ist eine deklarative Sprache zum Erstellen, Speichern und Teilen interaktiver Visualisierungsdesigns. Ab Version 5.11 unterstützt sie einige ARIA-Attribute für die Ausgabe von SVG-Dateien:
aria
schließt ARIA-Attribute in SVG-Dateien ein. Der Standardwert ist
true
. Beifalse
wird dasaria-hidden
-Attribut für die entsprechende SVG-Gruppe gesetzt.description
liefert in
aria-label
eine Textbeschreibung des SVG-ELements, wennaria
den Werttrue
hat.
Siehe auch
Mit Flight Passengers Example gibt es ein Beispiel
für die Verwendung der Vega-Anweisungen aria
- und description
durch
Vega-Lite:
Die horizontalen Linien sollen nicht zugänglich werden. Daher wurde in der Vega-Konfigurationsdatei
flight-passengers.vg.json
die horizontale Linie mit"aria": false,
ausgezeichnet.108 "marks": [ 109 { 110 "type": "line", 111 "aria": false, 112 "from": {"data": "traffic"}, 113 "encode": { 114 "enter": { 115 "x": {"scale": "x", "field": "unit0"}, 116 "y": {"scale": "y", "field": "change"}, 117 "stroke": {"value": "steelblue"}, 118 "strokeWidth": {"value": 3} 119 } 120 }, 121 "zindex": 2 122 },
In der generierten SVG-Datei
flight-passengers.svg
erhält die zugehörige Gruppe dadurch die Annotationaria-hidden="true"
:69 <g class="mark-line role-mark" aria-hidden="true"> 70 <path d="M24.000000019013836,20.112588094658268L93.2076502901645,26.132110486376767L160.09289618980006,14.924455087752282L229.2076502860901,20.695076449129235L298.32240438238017,9.587662748507821L362.9781420853612,109.65285552622753L432.0000000067907,164.6837644873604" stroke="steelblue" stroke-width="3"/> 71 </g>
Die Markierungen in der Zeitachse erhalten hingegen eine ausführliche Beschreibung (Englisch
description
) mit Monat, Jahr und prozentualer Veränderung zum Vorjahr:123 { 124 "type": "symbol", 125 "from": {"data": "traffic"}, 126 "encode": { 127 "enter": { 128 "description": { 129 "signal": "timeFormat(datum.unit0, '%B %Y') + ': ' + format(datum.change, '+.1%') + ' change from prior year'" 130 }, 131 "tooltip": { 132 "signal": "format(datum.change, '+.1%')" 133 }, 134 "x": {"scale": "x", "field": "unit0"}, 135 "y": {"scale": "y", "field": "change"}, 136 "fill": {"value": "steelblue"} 137 } 138 }, 139 "zindex": 2 140 }
In der generierten SVG-Datei erhalten die Pfade dadurch ein entsprechendes
aria-label
:72 <g class="mark-symbol role-mark" role="graphics-object" aria-roledescription="symbol mark container"> 73 <path aria-label="October 2019: +6.1% change from prior year" role="graphics-symbol" aria-roledescription="symbol mark" transform="translate(24.000000019013836,20.112588094658268)" d="M4,0A4,4,0,1,1,-4,0A4,4,0,1,1,4,0" fill="steelblue"/> 74 <path aria-label="November 2019: +2.0% change from prior year" role="graphics-symbol" aria-roledescription="symbol mark" transform="translate(93.2076502901645,26.132110486376767)" d="M4,0A4,4,0,1,1,-4,0A4,4,0,1,1,4,0" fill="steelblue"/> 75 <path aria-label="December 2019: +9.7% change from prior year" role="graphics-symbol" aria-roledescription="symbol mark" transform="translate(160.09289618980006,14.924455087752282)" d="M4,0A4,4,0,1,1,-4,0A4,4,0,1,1,4,0" fill="steelblue"/> 76 <path aria-label="January 2020: +5.7% change from prior year" role="graphics-symbol" aria-roledescription="symbol mark" transform="translate(229.2076502860901,20.695076449129235)" d="M4,0A4,4,0,1,1,-4,0A4,4,0,1,1,4,0" fill="steelblue"/> 77 <path aria-label="February 2020: +13.4% change from prior year" role="graphics-symbol" aria-roledescription="symbol mark" transform="translate(298.32240438238017,9.587662748507821)" d="M4,0A4,4,0,1,1,-4,0A4,4,0,1,1,4,0" fill="steelblue"/> 78 <path aria-label="March 2020: −55.6% change from prior year" role="graphics-symbol" aria-roledescription="symbol mark" transform="translate(362.9781420853612,109.65285552622753)" d="M4,0A4,4,0,1,1,-4,0A4,4,0,1,1,4,0" fill="steelblue"/> 79 <path aria-label="April 2020: −93.6% change from prior year" role="graphics-symbol" aria-roledescription="symbol mark" transform="translate(432.0000000067907,164.6837644873604)" d="M4,0A4,4,0,1,1,-4,0A4,4,0,1,1,4,0" fill="steelblue"/> 80 </g>