Datenvisualisierung/interaktive Landkarten

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Bei einem Einsatz von Landkarten auf Webseiten bietet sich SVG als Format an, da Flächen und Orte aus gezeichneten Formen bestehen, die man dann mit CSS gestalten und sogar animieren kann.

Landkarten spielen eine große Rolle bei der Datenvisualisierung, da sie anschaulicher und besser als lange Tabellen sind.

Woher bekommen Sie SVG-Karten?

Natürlich müssen Sie Ihre Karten nicht selbst zeichnen oder bei einem professionellen Kartendienst kaufen.

Es gibt auch Wege, um SVG-Karten aus openstreetmap[3] zu erzeugen, die Sie dann einbinden können.

Natural Earth ist eine Sammlung von geografischen Daten, die unter Public Domain stehen. Dieses Tutorial von smashing magazine zeigt Ihnen, wie Sie daraus mit dem Framework Kartograph.py eigene Karten erzeugen können.

interaktive Landkarte

Diese Karte zeigt Australien. Wenn Sie über die einzelnen Bundesstaaten mit der Maus fahren, erscheint deren Name.

Beispiel ansehen …
path {
  fill: #c32e04;
  stroke: #333;
  stroke-width: 0.4;
}

path:hover {
  fill: #dfac20;
}
	
text {
  opacity: 0;
  font-size: 8px;
  fill: black;
  pointer-events: none;  
}
	
path:hover ~ text {
  opacity: 1;
}
Bei :hover verändert das Pfad-Element seine Füllfarbe; zugleich wird der vorher mit opacity: 0 ausgeblendete Text sichtbar.

Der Selektor path:hover ~ text wirkt dank des Geschwisterselektors auf alle text-Elemente, die jüngere Geschwister von path sind und mit path das gleiche Elternelement haben.
Normalerweise würde der Pfad, wenn die Maus über dem Text schwebt, seinen :hover-Status verlieren. Durch die CSS-Eigenschaft pointer-events: none können Sie dies abschalten.

Ausschnitt aus dem SVG-Markup:
<g id="ACT"  aria-labelledby="ACTInfo">
    <path d="M246 186C246 ...z"/>
    <text x="200" y="200" id="ACTInfo">Australian Capital Territory</text>  
</g>

Da sowohl das g-Element als auch der Pfad selbst keine semantische Bedeutung haben, wird mit einem aria-labelledby-Attribut auf das benachbarte text-Element hingewiesen.

Nachteilig an dieser Methode ist die Tatsache, dass Textfelder, die über den zugehörigen Pfad herausragen, durch nachfolgende andere Pfade überschrieben werden. Da es in SVG (werder in 1.1 noch in SVG2) noch kein z-index gibt, kann ein Objekt nur durch eine spätere Position im Markup nach vorne gebracht werden.

frei positionierbare Tooltipps

In diesem Beispiel wird die Textinformation in einen Tooltipp gelegt.

Beispiel
  <defs>
    <symbol id="tooltipp">
	  <path d="..." fill="#666" stroke="black" stroke-width=".25" />  
	</symbol>
  </defs>

...

<g class="info" id="NswInfo" transform="translate(200,120)">
    <use href="#tooltipp" />
    <text x="5" y="12">New South Wales</text> 
</g>

Die Form des Tooltips wird in einem wiederverwendbaren symbol angelegt und dann innerhalb eines g-Elements mit use wieder aufgerufen. Der Text wird nicht wie in HTML als Kindelement, sondern einfach als nächstes Geschwisterelement notiert.

Verknüpfung von Kartendaten und Tooltip
<a id="NSW" aria-labelledby="NswInfo" tabindex="0" >
    <path class="land" d="..." />
</a>

<g class="info" id="NswInfo" transform="translate(200,120)">
    <use href="#tooltipp" />
    <text x="5" y="12">New South Wales</text> 
</g>

Die Koordinaten der Landflächen werden zuerst, anschließend die einzelnen Tooltips notiert. So wird sichergestellt, dass die Tooltips über den Landflächen dargestellt werden.

Der Pfad ist in einem a-Element umschlossen, das durch tabindex="0" auch mit der -Taste anwählbar und über das aria-Attribut mit dem Tooltipp verbunden ist.


Und nun das fertige Beispiel:

Beispiel ansehen …
.land {
  fill: #fffbf0;
  stroke: #e7c157;
  stroke-width: 0.4;
}

.land:hover,
a:focus .land {
  fill: #dfac20;
  stroke:#333;
}
	
.info {
  opacity: 0;
  font-size: 8px;
  fill: white;
  pointer-events: none;  
}
	
#ACT:hover ~ #ActInfo,  #ACT:focus ~ #ActInfo,
#NSW:hover ~ #NswInfo,  #NSW:focus ~ #NswInfo,
#NT:hover ~  #NtInfo,   #NT:focus ~  #NtInfo,
#QLD:hover ~ #QldInfo,  #QLD:focus ~ #QldInfo,
#SA:hover ~  #SaInfo,   #SA:focus ~  #SaInfo,
#TAS:hover ~ #TasInfo,  #TAS:focus ~ #TasInfo,
#VIC:hover ~ #VicInfo,  #VIC:focus ~ #VicInfo,
#WA:hover ~  #WaInfo,   #WA:focus ~  #WaInfo {
  opacity: 1;
  transition: all 0.5s linear;
}

Bei :hover verändert die Landfläche ihre Füllfarbe; zugleich wird der vorher mit opacity: 0 ausgeblendete Tooltipp sichtbar.

Der Selektor #ACT:hover ~ #ActInfo wirkt dank des Geschwisterselektors auf alle Tooltipps, deren g-Element ja jüngeres Geschwister des Links mit der Landfläche ist. Da das a-Element den Pfad der Landfläche umfasst, kann man die aktive Fläche des Links pixelgenau ansprechen.

Sie können die Link-Elemente auch mittels eines internen Ankers mit den Tooltipps verbinden, sodass sie fest selektierbar sind:

Beispiel
<a id="ACT" href="#ACT-info">
  <path class="land" d="..."/>
</a>

<g class="info ACT" id="href-info" transform="translate(225,155)">
  <use href="#tooltipp" />
  <text x="5" y="12">Canberra</text> 
</g>

Fazit

  • Die mögliche Überlagerung des Tooltips durch nachfolgende Kartendaten wird so vermieden.
  • Allerdings sind die CSS-Regelsätze mit den Geschwisterselektoren grenzwertig. Für Australien mag das noch gehen; die 50 Bundestaaten der USA oder die 294 Landkreise Deutschlands können so nicht umgesetzt werden.

Dynamische Selektion von Kartenausschnitten

Im SELF-Forum wurde gefragt, wie man für einen Kartenausschnitt einen :hover-Effekt mit JavaScript auslösen kann.[4] Dies ist nicht möglich; mit focus kann man einem Element aber den Fokus geben und denselben Effekt erzielen.

Kartenausschnitte mit JavaScript markieren ansehen …
document.querySelector('#find').addEventListener('click', setFocus);

function setFocus() { 
    let state = document.querySelector('[type="search"]').value;
    console.log(state);
    document.getElementById(state).focus();
}

Das Beispiel enthält nun noch ein Suchformular, bei dem mit datalist Suchvorschläge angeboten werden. Um das Beispiel-Script so einfach wie möglich zu halten, werden nur die Abkürzungen, die sich als ID der Kartenausschnitte wiederfinden, aufgelistet.

Bei einem Klick auf den Finden-Button wird der Wert des Suchformulars ausgelesen und das entsprechende Element erhält mit document.getElementById(state).focus(); den Fokus.

Die Formatierung selbst wird wieder über CSS realisiert.

Choroplethenkarte

Eine Choroplethenkarte oder auch Flächenkartogramm ist eine Karte in der die Gebiete nicht willkürlich, sondern je nach zugehörenden Daten in unterschiedlichen Schattierungen gefärbt, schattiert, gepunktet oder schraffiert sind. Passende Daten wären keine absoluten Zahlen wie die Einwohnerzahl eines Gebietes, sondern auf die Fläche bezogene wie Bevölkerungsdichte, -wachstum oder die prozentualen Werte für Arbeitslosigkeit, Mietpreise etc.[5]

Für das Farbschema gibt es mit ColorBrewer ein bequemes Tool, das Ihnen passende Farbpaletten zusammenstellt.

Screenshot

Die Karte ist ebenfalls aus der Wikipedia und mit SVG-Optimizer vereinfacht worden. Peter Collingridge setzte die :hover-Effekte in seinem Beispiel noch mit mouseover um, heute reicht dafür CSS alleine.[6]

Beispiel ansehen …
.land {
  fill: #fffbf0;
  stroke: #e7c157;
  stroke-width: 0.5;
}
.land:hover, .land:focus {
   stroke: #00000;
   stroke-width: 1.5;
}

Bei :hover wird die Randlinie schwarz und dicker dargestellt.


Empfehlung: Statt verschiedener Farben können Sie auch eine Farbe verwenden und die Deckkraft stufenweise verändern.


Im realen Einsatz empfiehlt es sich, die interaktive Karte als SVG-Dokument (→ Einzelansicht) in einem object-Element einzubinden, da ältere Versionen des Internet-Explorer die inline SVG-Grafik in der Standardgröße von 300x150px darstellen. Leider ist ein solches Beispiel mit der Mediawiki-Software (noch) nicht möglich.

Einbindung mit object
<object 
    data="Deutschland-Arbeitslose.svg" 
    type="image/svg+xml">

    <param name="src" value="/local/Deutschland-Arbeitslose.svg">
    <!-- Fallback -->
    <img src="Deutschland-Arbeitslose.png" alt="Choropletenkarte der Arbeitslosenquote der Bundesländer">
</object>

Karte mit .csv-Daten füllen

Dies ist ein sehr gutes Tutorial, wie man eine vorhandene SVG-Karte mit in einer Daten aus einer CSV-Datei mit aus der Wikipedia gewonnenen Daten dynamisch füllt. Die Skripte sind allerdings in Python geschrieben.

mit dem Viewport zoomen

SVG Zoom



Siehe auch

  • Einstieg in Leaflet

    SELF-Blog-Artikel von Jürgen Berkemeier,
    Leaflet ist eine API, um Karten in Webseiten einzubinden

  • Geolocation API
  • responsive Imagemaps

    Klickflächen innerhalb eines Bilds? -


    Das wird jetzt mit SVG gemacht!

Weblinks

  1. http://www.amcharts.com/svg-maps/
  2. wikimedia: Category:SVG_maps_by_country
  3. http://wiki.openstreetmap.org/wiki/SVG
  4. SELF-Forum: Frage zum Wiki-Artikel „SVG_und_JavaScript“ vom 09.12.2021
  5. flowingdata: How to Make a US County Thematic Map Using Free Tools
  6. Peter Collingridge: Interactive SVG map