-
Notifications
You must be signed in to change notification settings - Fork 0
Product Biografie | Rafi Ijssel
Toen we begonnen aan dit project, was het eerste idee best wel standaard: laten we de verzamelde data van de Visdeurbel in een mooie grafiek of tijdlijn zetten. Maar toen dacht ik: we hebben het over vissen in een Utrechtse gracht! Dat smeekt gewoon om een veel visuelere aanpak. Daarom heb ik het roer omgegooid en ben ik de gracht digitaal gaan nabouwen.
In dit verslag neem ik je mee door mijn proces. Van het eerste idee tot de grappige bugs die ik moest oplossen, en hoe ik de boel uiteindelijk soepel en gebruiksvriendelijk heb gekregen.
Voordat ik kon beginnen met tekenen, moest ik eerst de data van de server (uit ons Astro-project) in mijn eigen JavaScript krijgen. Een server en een browser praten namelijk niet zomaar direct met elkaar.
Ik heb dit opgelost door een 'bruggetje' te bouwen. De server zet de data voor me klaar in een soort onzichtbaar pakketje op de webpagina (window.SERVER_VIS_DATA). Mijn code pakt dat pakketje vervolgens uit. Ook heb ik er een veiligheidscheck ingebouwd (|| []), voor het geval de server even hapert en per ongeluk een leeg pakketje stuurt. Zo crasht in ieder geval niet meteen de hele website!
// Zo haal ik de data veilig op en zet ik platte tekst om naar een echte datum
const rawData = window.SERVER_VIS_DATA || [];
const data = rawData.map((item) => ({
...item,
created_at: item.created_at ? new Date(item.created_at) : null,
}));
// Laat de vissen maar los!
initAquarium(data);Het begon hier allemaal bij deze grafiek.

Het moest alleen echt wat beter want dit was natuurlijk niet heel leuk uit.
Ik heb er voor gezorgd dat het "aquarium" er wat levediger uit zag. Ik heb hierbij voor gezorgd dat er bubbels van beneden naar boven gaan. Ook heb ik een laagje zand of slib toegevoegd op de bodem. Ook heb ik van de assets die we hebben gekregen van Studio Moan de planten en de fiets gebruikt. Die heb ik op de bodem gezet. Als feedback had ik ook gekregen dat er verschillende opties moesten komen over wat je kan zien, dus heb ik ook een top 3 meest gespotte vissen toegevoegd. Dan komen alleen de meest gespotte in het aquarium en bovenin zie je hoe de vissen heten met een image erbij. Dat heb ik ook nog toegevoegd.
Het aquarium waarbij alle vissen te zien zijn
Het aquarium met de top 3 vissen
Het probleem was dat alles nu gewoon een beetje te breed was. Het aquarium ging helemaal van de linkerkant van het scherm naar de rechter en dat zag er gewoon niet zo heel mooi uit. Het moest allemaal wat smaller. Hoe dat is opgelost is door de visnamen naast de gracht zelf neer te zetten. Zo zag het er allemaal net wat beter geordent uit.
Dat heb ik dus zo eruit laten zien. Dit is alleen natuurlijk nog niet echt in de stijl van de website. Dat heb ik dan ook nog moeten aanpassen. De knoppen waren nog niet goed en het zag er allemaal een beetje leeg uit nog op de bodem.
De gracht in de juiste huisstijl
Een aquarium moet wel echt aanvoelen. Daarom heb ik de gracht (MainAquarium.astro) flink aangekleed met een dieptemeter, een verzonken fiets, en waterplanten.
Om het water er een beetje troebel en Utrechts uit te laten zien, heb ik geëxperimenteerd met CSS-trucjes. In plaats van extra HTML-elementen toe te voegen (wat de code rommelig maakt), heb ik met CSS pseudo-elementen (::before) een soort modderige filterlaag over de achtergrond gelegd.
Ook heb ik luchtbellen toegevoegd voor de sfeer. Een klein stukje JavaScript maakt willekeurig belletjes aan, en CSS zorgt ervoor dat ze vrolijk naar boven drijven en een beetje heen en weer wiebelen:
/* De magie achter de zwevende bubbels */
@keyframes float-up {
0% { transform: translateY(0) translateX(0) scale(1); opacity: 0; }
50% { transform: translateY(-300px) translateX(15px); }
100% { transform: translateY(-650px) translateX(-15px); opacity: 0; }
}Stel je voor dat alle vissen even groot zijn en even snel zwemmen... dat is toch super saai? Ik wilde dat het er natuurlijk uitzag. Omdat we soms honderden vissen in de data hebben, laat ik er maximaal 7 per soort zien. Anders wordt het één grote vissen-soep.
Daarnaast heb ik de vissen eigenschappen gegeven. Een gigantische Meerval is natuurlijk veel groter en trager dan een kleine, snelle Alver. Ik heb dit geregeld met een handig overzichtje in de code:
// Hoe groot is de vis?
const fishScaleMap = {
"Alver": 0.5, // Ukkie
"Meerval": 2.2 // Gigant
};
// Hoeveel seconden doet hij erover om het scherm over te zwemmen?
const fishSpeedMap = {
"Alver": 10, // Super snel
"Meerval": 35 // Lekker op z'n gemakje
};Samen met een klein beetje toeval (Math.random()) zorgt dit ervoor dat ze allemaal op een andere hoogte beginnen en net iets anders zwemmen. Ook heb ik een tooltip gemaakt met de naam van de vis die je muis volgt als je eroverheen gaat!
Naast het aquarium zit een legenda om vissen te filteren. Eerst bouwde ik dit met simpele tekst-tags en heel veel JavaScript om bij te houden op welke vis je had geklikt. Dit werkte, maar de code werd al snel een rommeltje.
Ik kwam op het idee om dit helemaal om te bouwen naar een onzichtbaar HTML-formulier met "radio-knoppen". Het briljante van een radio-knop is dat de browser zelf onthoudt welke je hebt aangeklikt. Ik kon al mijn ingewikkelde JavaScript weggooien en gewoon CSS gebruiken om de geselecteerde knop paars te kleuren!
/* Als de (onzichtbare) radio-knop is aangevinkt, geef de knop ernaast dan een mooi kleurtje */
.aquarium-filters input[type="radio"]:checked + .filter-btn {
background: var(--color-purple);
color: white;
}Omdat dit menu best lang werd, werkte de layout niet meer zo mooi. Met CSS Flexbox heb ik ervoor gezorgd dat het aquarium aan de linkerkant netjes meerekt met de hoogte van het menu aan de rechterkant.
Het aquarium moet natuurlijk door iedereen te gebruiken zijn, ook als je geen muis hebt en met je toetsenbord (Tab en de pijltjestoetsen) navigeert. Hier liep ik tegen twee hele grappige, maar lastige bugs aan:
-
De Pijltjes-bug: Toen ik met mijn pijltjestoetsen door het menu wilde navigeren, gebeurde er niets als ik op 'Omhoog' drukte. Hoe dat kon? Ik had de radio-knoppen visueel verborgen door ze in CSS uit de lijst te trekken (
position: absolute). Hierdoor legde de browser ze onzichtbaar op één grote stapel. Als ik 'omhoog' wilde, raakte de browser in de war. Ik heb dit gefixt door de knoppen weer gewoon in de lijst te zetten, maar ze0 pixelshoog te maken. - De Spelletjes-kaper: Een ander stuk code (van de 'Raad de Vis' game) had een script dat luisterde naar de pijltjestoetsen, en kaapte daarmee per ongeluk de pijltjes voor de hele website weg! Ik heb een check toegevoegd die kijkt: "Hey, zit de bezoeker eigenlijk wel in het spelletje?" Zo nee, dan mag je de pijltjes gewoon gebruiken voor het aquarium.
Als laatste heb ik de boel netjes afgewerkt:
- Mobielvriendelijk: Op een grote computer is het prachtig om veel waterplanten en hout in het aquarium te hebben. Maar op een mobieltje wordt het snel te druk en te traag. Via CSS Media Queries verberg ik bepaalde decoratie volledig als je scherm kleiner is dan 1100 pixels.
-
Astro Server Fix: Omdat ons Astro-framework de website eerst 'bouwt' op een server, liep hij vast op onderdelen die alleen een webbrowser snapt. Ik heb er een onzichtbare muur omheen gebouwd (
if (typeof window !== "undefined")) zodat deze code pas wordt uitgevoerd als de pagina echt op je scherm staat.
Ik ben super trots op het resultaat! Ik heb geleerd hoe je ruwe data kunt omzetten in iets visueels, hoe je slim gebruik kunt maken van HTML-formulieren, en hoe belangrijk het is om na te denken over toegankelijkheid. Het aquarium is nu niet zomaar een plaatje, maar een interactief, speels en robuust onderdeel van de website geworden.
- https://visdeurbel.nl/
- https://d3js.org/getting-started
- https://observablehq.com/@d3/gallery?utm_source=d3js-org&utm_medium=page-nav&utm_campaign=try-observable
- https://bewegingnl.com/web-animation-netherlands/scroll-geactiveerde-effecten-implementeren/
- https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
- https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/gap
- https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/cursor
- https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax
- https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Grid_layout
- https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Flexible_box_layout/Basic_concepts