-
Notifications
You must be signed in to change notification settings - Fork 0
Datavisualisatie maken
D3 is een JavaScript library die je de mogelijkheid geeft om op basis van data documenten aan te passen. Ik heb het nog nooit zelf gebruikt, en ben erg benieuwd wat je er allemaal mee kan.
Om te beginnen heb ik een van de vele video's van Curran gekeken. Hij is een ware D3 guru, en legt in zijn 2018 course uit hoe je van iemand die nog nooit met JS heeft gewerkt een D3 guru wordt, net zoals hem. Ik vind zijn video's echter vrij traag, dus ben na het maken van mijn eigen D3 Face aan de slag gegaan met het implementeren van D3 zoals ik het wil gebruiken.
Aan de hand van mijn schetsen wilde ik alvast beginnen met het maken van een wijzerplaat. Deze wijzerplaat bestaat uit 12 lijnen, met aan het einde van elke lijn een uur. De uren moeten uiteindelijk dynamisch in te stellen zijn, maar voor nu houden we het nog even statisch.
De SVG lines opstellen is nog niet zo heel erg ingewikkeld. Een belangrijke les uit de video van Curran is dat je je code niet moet herhalen, maar leesbaar moet houden, dus ik heb gelijk de berekeningen die vaker voorkomen weggeschreven in een function die ik ook kan aanroepen in andere functies. Nu kan ik dus bijvoorbeeld de uren ook heel makkelijk op plek zijn waar ik ze wil hebben met dezelfde berekeningen.
Over de uren gesproken, dat was nog wel een klein dingetje. Toen ik de teksten er voor het eerst in zetten, wist ik helemaal niet hoe je de tekst kon uitlijnen. Het blijkt namelijk dat je niet met dezelfde CSS attributes dit doet in SVG. Na wat rond gegoogled te hebben kwam op op text-anchor en alignment-basline. Hiermee kan je de tekst horizontaal en verticaal uitlijnen, en het dus binnen de buitenrand van de SVG houden, mocht je het er recht tegenaan zetten.
Dan nog de tekst in het midden, die aangeeft welke hotspot is geselecteerd. Dat kan je blijkbaar met HTML tags doen als je deze in een zogeheten foreignObject zet. Deze kan je makkelijk centreren met transform, dus het centreeren van dit element was appeltje eitje.
Wat ik nu heb is een vierkante klok met uren en een tekst in het midden die de hotspot zal weergeven. Ik heb alleen geen flauw idee hoe ik verder moet. Ik doe alles van scratch, maar heb geen flauw idee of dit wel de beste aanpak is.
Daarom ben ik in gesprek gegaan met Robert om te vragen wat het handigst is om te doen. Hij vertelde me dat het niet echt handig is om eht wiel opnieuw uit te vinden. Daar was ik het deels met hem eens, omdat wat ik tot nu heb gemaakt sowieos vrij statisch blijft en ik het daarom dus niet erg vond om het wiel deels opnieuw uit te vinden.
Hij vertelde me over de clock visualisations, radial/conic barcharts en polar scatter plots. Hij gaf me ook nog eens deze link om vanuit verder te werken. Ik wilde er gelijk mee aan de slag.
Aan de hand van de termen die Robtert me heeft gestuurd, ben ik verder gegaan met onderzoeken naar manier om m'n concept tot werkelijkheid te brengen. Het eerste wat ik deed was de code die ik had omvormen naar een polar plot. Daar begon ik vrijdag mee en maakte ik maandag af. Vanaf toen was het smooth sailing en heb ik in een paar dagen tijd de visualisatie werkend gekregen met data en interactiviteit toegevoegd.
De app start wanneer de pagina wordt geladen, en bouwt alvast de klok en het formulier voor het veranderen van variabelen op terwijl de data van het RDW wordt ingeladen. Deze variabelen bepalen welke data wordt ingeladen, en zijn dus allemaal aan te passen met de controls die op de pagina staan. Bij elke verandering een van van deze controls, worden de variabelen bijgewerkt en de onUpdate
function uitgevoerd. Deze function maakt de data gereed voor rendering en geeft de data door aan de renderer. De variabelen hebben een standaard waarde die bij het inladen van de website worden gebruikt. onUpdate wordt dus ook gecallt wanneer de data voor het eerst is ingeladen.
De render
function neemt de bruikbare data aan, en plot deze op de grafiek met een enkele D3 functional chain. Het formulier wordt ook geüpdate met de nieuwste waarden, zodat je weet met welke waardes je aan het werken bent. Dit allemaal gebeurt alleen in deze function, wat structuur geeft aan de app.
Bij elke render wordt de data over svg circle
s gezet, die op hun plek worden gezet door middel van een D3 lineRadial. Die berekent dus de locatie van de dot op basis van de openingstijd of sluitingstijd en de afstand tot de hotspot van het parkeergebied. De lineRadial converteert deze twee waardes naar een hoek en een radius op basis van twee schalen die mee zijn geconfigureerd bij de lineRadial. Wanneer een circle voor het eerst wordt aangemaakt, animeert deze vanuit het middenpunt van de grafiek naar zijn positie, en van oude naar nieuwe positie bij subsequente 'updates'. Dit vindt allemaal plaats in een .join
, die een enter function en een update function heeft aangenomen. Exits worden niet geanimeerd. Er is zoveel data dat nog meer animaties extreem onoverzichtelijk wordt. Na de .join wordt er nog wat styling toegepast, wat buiten de update logica plaatsvindt, en event listeners voor de toaster toegepast. Die wordt namelijk getoond wanneer je over een circle heen hovert.
Elk form element heeft natuurlijk een eigen variabele die wordt aangepast, dus voor elke variabele is een aparte function geschreven die de variabele update, en onUpdate uitvoert. De onUpdate neemt dan die geüpdate variabelen en past ze toe op de data-preparatie.
Dit allemaal vindt plaats in de chartApp function, die wordt gerunt op het moment dat de webpagina is geladen. Zo blijft alles self-contained, overzichtelijk en makkelijk leesbaar.
- Huidige hotspot.
- De keuze voor het tonen van opening- of sluitingstijd.
- Het bereik van de getoonde uren.
- Het bereik van de afstand tot de hotspot.
- Het wel of niet tonen van de parkeergebieden zonder openingstijden.
Ik heb veel geleerd over D3, en het toepassen van verschillende aspecten van D3 om alles te maken wat je wilt. Hier is een overzichtje van alles wat ik heb geleerd en toegepast van D3
- lineRadial voor het maken van een plotter die de parkeerplekken op de juiste plek in de grafiek neerzet. Dit doe je met een radius en een angle, die de waardes die je meegeeft converteert naar een punt binnen je radial line.
- scaleLinear voor het maken van een schaal. Dit gaat op basis van een domain en een range, waarbij de waardes binnen een domain worden omgezet naar de corresponderende waarde in een range.
-
select/selectAll voor het selecteren en manipuleren van 1 of meerdere SVG en andere elementen op de pagina.
- .append voor het toeveogen van elementen aan je pagina.
- .data voor het manipuleren van HTML en SVG elementen op basis van de data die wordt doorgegeven.
- .join voor het automatisch toevoegen, updaten, en verwijderen van HTML/SVG elementen op basis van de hoeveelheid data beschikbaar
- .attr om attributen aan te passen van een element, wat dus kan met data als je de de .data en .join functies hiervoor gebruikt. Echt heel vet
- .text om tekst binnen een element aan te passen, wat dus kan met data als je de de .data en .join functies hiervoor gebruikt. Echt heel vet
- .classed om CSS classes toe te voegen of te verwijderen van je
-
range voor de basis-uitlijning van de uurplaat-lijnen. Je geeft een min, max en stapgrootte mee, en je krijgt een array terug die oploopt van je min naar je max met tussenstappen die toenemen met de stapgrootte die je meeneemt.
range(0, 360, 30)
geeft[0, 30, 60, 90, 120, 150, 180...360]
.
- Polar Plot (v4) van Vikky Ambarkar voor de opzet van een polar plot, en hoe je het überhaupt moet schrijven.
- d3.lineRadial van Fil en Dit stackoverflow antwoord van ene Mark voor het maken van mijn plotter.
© Jonah Meijers, 2020 🦧
Deze links verwijzen naar pagina's buiten deze wiki. Je zal de wiki dus verlaten als je op een van deze links klikt.