[DajSięPoznać#4] Mapa Krakowa w SVG

Wstęp

Do wizualizacji statystyk oprócz tradycyjnych wykresów przyda się także interaktywna mapa miasta podzielona na dzielnice.  Przykładowo, te dzielnice, w których ceny za metr kwadratowy mieszkania są najwyższe, będą na mapie znaczone ciepłymi kolorami, a te z najtańszymi, kolorami chłodnymi. Kształty dzielnic w SVG można znaleźć na wikipedii.

Dlaczego SVG ?

SVG dawno już przestał być tylko jednym z formatów obrazka, a jest czymś w rodzaju deklaratywnego języka do definiowania grafiki. Główną zaletą jest oczywiście skalowalność takich grafik bez utraty jakości. Elementy svg można zarówno embeddować w html-u, jak i wstawiać z zewnętrznych źródeł, np. poprzez tag object. SVG daje także możliwość animowania elementów i to na trzy sposoby: przez CSS3, z kodu (np. snap.svg) oraz poprzez SMIL – deklaratywny język, który osadza się w markupie.

Mapa

Wszystkie kształty zostały zaszyte w widoku Aurelii, głównie dlatego, żeby to wszystko załadowało się jednym requestem. Ponieważ tag path (reprezentujący zamknięte obszary) jest pełnoprawnym elementem drzewa DOM, to możemy się do niego bindować poprzez framework.

<template>        
        <svg xmlns="http://www.w3.org/2000/svg" xmlns:odm="http://product.corel.com/CGS/11/cddns/" xml:space="preserve" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd"
             viewBox="0 0 210000 148000">
        <g>
            <path id="Czyżyny" class="str0" mouseover.delegate="selectDistrict($event) & throttle" mouseout.delegate="leaveDistrict($event) & throttle"
                   d="M126039 72604l-2277 1442 -2125 1442 -2049 76 -2201 -683 -1746 -1973 -1897 -607 -1746 986 -1214 2429 -1138 1214 -1594 304 -2049 -987 -2732 -2808 -1215 -2353 -1138 -2732 -911 -1290 -1366 -1214 -2201 0 -227 -1056 -955 -956 68 -751 1024 -478 1707 -341 1638 -137 410 -683 -2321 -1843 -2253 -1775 1775 -1502 1160 -887 -136 -1161 546 -887 -410 -1229 -205 -956 683 -478 -68 -1092 -615 -1229 -1092 -409 -1707 0 -751 -342 69 -1297 2267 -547c0,0 1822,0 2201,0 380,0 2732,-152 2732,-152l2733 -151 1518 -152 1897 1290 2201 531 -531 2429 1897 835 152 1897 607 683 1669 987 -1062 1366 -1290 607 0 683 1593 303 2429 0 1214 380 683 683 -607 911 -379 1290 152 1973 1138 455 1745 1063 1367 -76 1442 911 1517 75 1215 0 531 911 -1442 -303 -1138 151 -228 1063 -607 759 -1442 1138 -76 1442 2201 1822 1290 76 1670 910z" />
                   <!-- Pozostałe dzielnice -->         
      </g>
    </svg>
    <h2 show.bind="selectedItem !== undefined">Dzielnica ${selectedItem} zawiera <b>${data[selectedItem]} ulic</b></h2>
</template>

ViewModel z handlerami dla zdarzeń wygląda następująco:

import {HttpClient} from "aurelia-http-client"

export class Map{
    constructor(){
    }
    
    activate(){
        var client = new HttpClient();
        this.data = {};
        this.details = undefined;

        var self = this;
        client.get("api/districts").then( response => {
            var response = JSON.parse(response.response);
            for(var i = 0; i < response.length; i++){
                var name = response[i].name;
                var element = document.getElementById(name);
                element.setAttribute("fill", `hsl(${8*i}, 100%, 50%)`);
                this.data[name] = response[i].streetsCount;
            }
        })
    }

    selectDistrict($event){
        $event.srcElement.classList.add("pulsar-animation");
        this.selectedItem  = $event.srcElement.id;
    }

    leaveDistrict($event){
        $event.srcElement.classList.remove("pulsar-animation");
        this.selectedItem = undefined;
    }

}

Kolejne kolory są przydzielane poprzez przesuwanie kąta hue co 8 stopni z modelu HSL, co zapewnia równy rozkład barw. Efekt jest całkiem ciekawy (dla poniższego rysunku sortowane względem liczby ulic):

map

Nadanie klasy pulsar-animation wprowadza CSS-ową animacją na opacity, która pojawia się, gdy najedziemy myszką na obszar i znika po wyjechaniu z niego:

@-webkit-keyframes pulsar {
  0%   { opacity: 1; }
  50%   { opacity: 0.3; }
  100% { opacity: 1; }
}
@-moz-keyframes pulsar {
  0%   { opacity: 1; }
  50%   { opacity: 0.3; }
  100% { opacity: 1; }
}
@-o-keyframes pulsar {
  0%   { opacity: 1; }
  50%   { opacity: 0.3; }
  100% { opacity: 1; }
}
@keyframes pulsar {
  0%   { opacity: 1; }
  50%   { opacity: 0.3; }
  100% { opacity: 1; }
}

.pulsar-animation {
  -webkit-animation: pulsar 1.4s infinite; /* Safari 4+ */
  -moz-animation:    pulsar 1.4s infinite; /* Fx 5+ */
  -o-animation:      pulsar 1.4s infinite; /* Opera 12+ */
  animation:         pulsar 1.4s infinite; /* IE 10+, Fx 29+ */
}
Advertisements

One thought on “[DajSięPoznać#4] Mapa Krakowa w SVG

  1. Pingback: [DajSięPoznać] Podsumowanie | When the smoke is going down

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s