Staafdiagrammen met animatie
In het item Staafdiagrammen wordt getoond hoe je met betrekkelijk eenvoudige middelen een staaf- of kolomdiagram op kunt zetten. Daar zit ook een applicatie bij om zo'n diagram te genereren.
Op deze pagina wordt code gepresenteerd die hetzelfde doet voor een staafdiagram, maar met een animatie die wordt getriggerd door aanwijzen met de muis of door aanraken.
Als je de code van zo'n diagram bekijkt blijkt er vaak helemaal geen ingewikkelde grafische representatie te zijn, alleen maar wat kleine .GIF-bestandjes. Elk van die bestandjes bevat een plaatje van één of hooguit een paar pixels; elk plaatje bevat één kleur.
De hier besproken code kun je downloaden voor eigen gebruik, inclusief de plaatjes.
- Er worden twee items besproken:
- Een voorbeeld van een Staafdiagram met animatie.
- De HTML en het JavaScript die hiervoor nodig is.
- Inspiratie voor dit item is ontstaan door de benchmarks op tweakers.net.
Voor deze site heb ik iets nagebouwd wat er op lijkt.
De code bestaat uit HTML en JavaScript. Gebruik van CSS is minimaal.
- Een Staafdiagram bevat liggende balken, waarvan de lengte staat voor een getal. Het is betrekkelijk eenvoudig om een legenda
direct bij de staven te zetten.
- De opzet van een Staafdiagram is als volgt:
- De hele figuur bestaat uit een tabel met drie rijen, elk met één cel.
- De bovenste rij/cel bevat de titel.
- De onderste rij/cel dient om wat witruimte te maken. Hier kan eventueel een ondertitel in worden gezet.
- De onderste rij/cel bevat zelf weer een tabel. In de bovenste rij/cel van deze tabel staat de titel van het staafdiagram (aantal "votes"); voor elke gegevensbalk is er een volgende rij.
- De rijen met gegevens bestaan elk uit twee cellen, nl. één voor de legenda (mooi, leuk, enz.) en het aantal malen dat het voorkomt en één voor de balk zelf.
- Het percentage van het geheel wordt vervolgens achter de balk geschreven.
- De balk is een figuur (.GIF), die slechts één pixel bevat. Door gebruik te maken van een vaste hoogte (constante staafBreedte, = 15) en die te gebruiken voor height, krijgt de balk een geschikte dikte.
- De lengte van de balk wordt ingesteld op basis van de te tonen gegevens met behulp van width="...".
- Om de kleuren van de balken te veranderen moet je de .GIF-bestanden veranderen. Hiertoe moet je het kleuren-palet van
de achtergrond aanpassen. De plaatjes zelf bevatten slechts één bit per pixel. Dit is voor de goede functie
overigens niet nodig. Elk .GIF-plaatje is bruikbaar. Voor het beste resultaat zijn ze wel zo klein mogelijk en bevatten ze
dus één kleur.
Het voorbeeld op deze pagina is geschikt voor statische diagrammen, d.w.z. met inhoud die niet steeds verandert.
- Bij dynamische diagrammen is de werkwijze anders.
Eerst worden de vereiste gegevens uit een database gehaald. Vervolgens wordt de HTML op de server door een speciaal programma in elkaar gezet en naar de browser gestuurd. Ook de plaatjes worden door dat programma gemaakt en naar de browser gestuurd. Dat kan overigens ook met CSS worden geregeld.
Op deze manier kun je de veranderingen in de database bijhouden en kun je dus steeds een recente grafiek laten zien. Dit valt buiten het bestek van deze pagina.
- De werking van het script
-
HTML - De HTML van het voorbeeld bestaat uit twee geneste tabellen, die gecentreerd in het document zijn geplaatst.
- De eerste tabel beslaat 90% van de breedte van het document en bevat twee rijen. De eerste rij bevat de titel. De tweede rij bevat de tweede tabel met het staafdiagram.
- De tweede tabel beslaat de volledige breedte van de eerste tabel en heeft vier kolommen.
- De eerste rij beslaat volledige breedte van de vier kolommen van de tabel en bevat de ondertitel. De tweede rij is leeg.
- De derde en volgende rijen bevatten het staafdiagram.
º In de eerste kolom wordt de beschrijving van de staaf gezet, samen met het aantal malen dat dit voorkomt.
º De tweede en de vierde kolom zijn leeg.
º In de derde kolom worden de staaf en het percentage neergezet. - Helemaal onderaan, buiten de tabellen, staan de beschrijvende tekst en de link om het venster te sluiten.
- JavaScript
- Het JavaScript staat helemaal in de <head>-sectie van het document. Het bestuurt het gedrag van het staafdiagram
via de events click (b_ij aanraakschermen) en mouseover / mouseout (bij gewone beeldschermen en een muis).
De event-handlers worden ingesteld met addEventListener().
- Het script begint met de declaratie van de constanten waarden en beschrijving. Dit zijn arrays waarin de getalswaarden en de bijbehorende beschrijving in worden gezet. Beide arrays moeten evenveel elementen hebben. Het aantal elementen wordt in de constante aantalWaarden bewaard.
- De constanten waarden en beschrijving zijn de enige zaken die moeten worden aangepast in het JavaScript om een staafdiagram te maken.
- Met de constanten staafBreedte en maxLengte kan het uiterlijk van de staven worden veranderd.
- In de variabele totaalWaarden wordt het totaal van de getallen in waarden opgeslagen. Het totaal wordt bepaald door de function somWaarden(), die voor elk getal in waarden wordt aangeroepen waarbij totaalWaarden wordt bijgewerkt via een side-effect. Het berekende totaal wordt in het document geplaatst via de id totalen.
- De staven worden getekend door de HTML. De tekst voor elke staaf wordt samengesteld uit de data in waarden en beschrijving
door de function toonWaarde(). Het percentage van elke staaf ten opzichte van het totaal wordt achter elke staaf gezet
door de function toonPercentage().
- Er wordt onderscheid gemaakt tussen aanraakschermen en "gewone" beeldschermen.
º Als er met een aanraakscherm op een staaf wordt getikt, wordt het percentage van die staaf ingesteld op 100% en wordt bij de andere staven het percentage t.o.v. de aangetikte staaf getoond door de function percentage100().
º Als er met een gewoon scherm met de muis over een staaf wordt bewogen, wordt het percentage van die staaf ingesteld op 100% en wordt bij de andere staven het percentage t.o.v. de aangewezen staaf getoond door de function percentage100(). Als de muis de staaf verlaat worden de oorspronkelijke percentages terug gezet door de function resetPercentages().
N.B.: Computers met een aanraakscherm én een muis gedragen zich alsof een muis niet aanwezig is. - De koppeling van percentage100() verloopt via een anonieme function. Het hoe-en-waarom hiervan wordt besproken
in het item Functions met parameters gebruiken in addEventListener.
- De function somWaarden(item) telt de waarde item op bij totaalWaarden. De aanpak met een aparte function is nodig om de methode ForEach te kunnen gebruiken, waarin het niet niet mogelijk is om parameters te gebruiken in een function-aanroep.
- De function toonWaarde(n) zet element n van de arrays beschrijving en waarden in de id's wrden.
- De function toonStaaf(n) berekent de lengte van de staaf (in px) en stelt die in, samen met de breedte van de staaf.
- De function toonPercentage(n) berekent voor waarden[n] het percentage van totaalAantal en zet dat in de id percn, afgerond op 1 decimaal. De afronding gebeurt met toFixed(1). Dit is een methode van het object number. Dit werkt alleen voor "echte" getallen, niet als het getal een string is.
- De function percentage100(n) berekent een percentage van een staaf ten opzichte van een staaf die op 100% is gezet door er met de muis boven te hangen of door aantikken. Ook hier wordt toFix(1) gebruikt om de getallen met 1 decimaal te laten zien.
- De function resetPercentages() zet de door percentage100(n) aangebrachte wijzigingen in het staafdiagram terug
naar de beginsituatie.
- Inbouwen in je eigen site
- Download de .zip-file en pak hem uit. Hernoem eventueel de file html825a naar index.html. Je hebt nu een werkend voorbeeld.
- Zet een lijst van getallen in de constante waarden. Zet de bijbehorende beschrijvingen in de constante beschrijving.
- Als er minder dan zes waarden/beschrijvingen zijn moet je de betreffende tabelregels in de HTML verwijderen.
- Als er meer dan zes waarden/beschrijvingen zijn moet je de betreffende tabelregels HTML toevoegen.
- De nummering van de diverse id's moet bij nul beginnen en mag geen gaten bevatten.
- Verander eventueel de breedte staafBreedte van de staven (staat nu op 15px).
- Verander eventueel de maximale lengte maxLengte van de staven (staat nu op 220px). Deze waarde wordt toegekend aan de hoogste waarde in waarden. De lengtes van de andere staven worden berekend ten opzichte van MaxLengte.
- Pas de kleuren aan naar je eigen smaak.
Gebruik:
- De code staat gedeeltelijk in de <HEAD> en gedeeltelijk in de <BODY>.
De code van het voorbeeld ziet er als volgt uit:
(Zet dit in de <HEAD>).
<script>
const waarden = [3,2,2,4,1,7],
beschrijving = ["Mooi","Handig","Nuttig",
"Leuk","Weet ik niet","Overbodig"];
const staafBreedte = 15;, maxLengte = 220;
/* ==== Hieronder niet meer wijzigen ==== */
const aantalWaarden = waarden.length;
let totaalWaarden = 0, maxWaarde = 0;
window.addEventListener('load', function() {
// Bepaal de som en de hoogste van waarden[]
waarden.forEach(somWaarden);
for (let i=0; i<aantalWaarden; i++) { // Toon de percentages na de balk
toonWaarde(i);
toonStaaf(i);
toonPercentage(i);
}
document.getElementById('totalen').innerHTML =
'<b>' + totaalWaarden + '</b>';
if ("ontouchstart" in document.documentElement) { // Aanraakscherm?
for (let i=0; i<aantalWaarden; i++)
document.getElementById('staaf'+i).addEventListener('click',function()
{percentage100(i)});
} else {
for (let i=0; i<aantalWaarden; i++) {
document.getElementById('staaf'+i).addEventListener('mouseover',
function() {percentage100(i)});
document.getElementById('staaf'+i).addEventListener('mouseout',
resetPercentages);
}
}
}); // event Load
function somWaarden(item) {
totaalWaarden += item;
if (item > maxWaarde) maxWaarde = item;
} // somWaarden
function toonWaarde(n) {
document.getElementById('wrde'+n).innerText =
beschrijving[n] + " " + waarden[n];
} //toonWaarde
function toonStaaf(n) {
document.getElementById('stl'+n).style.height =
staafBreedte + "px";
document.getElementById('stl'+n).style.width =
waarden[n] / maxWaarde * maxLengte + "px";
} //toonStaaf
function toonPercentage(n) {
let helper = waarden[n] / totaalWaarden * 100;
document.getElementById('perc'+n).innerText =
helper.toFixed(1) + "%";
} // toonPercentage
function percentage100(n) {
let helper = 0.;
for (let i=0; i<aantalWaarden; i++) {
if (i == n || waarden[i] == waarden[n]) {
helper = 100;
document.getElementById('perc'+i).innerText =
helper.toFixed(1) + "%";
} else {
helper = (waarden[i] - waarden[n]) / waarden[n] * 100;
if (helper < 0) document.getElementById('perc'+i).innerText =
helper.toFixed(1) + "%";
else document.getElementById('perc'+i).innerText =
"+" + helper.toFixed(1) + "%";
}
}
} // percentage100
function resetPercentages() {
for (let i=0; i<aantalWaarden; i++) toonPercentage(i);
} // resetPercentages
</script>
(Zet dit in de <BODY> op de plaats waar het diagram moet verschijnen)
<div align="center">
<table border="1" cellspacing="1" cellpadding="2" bgcolor="#ddeeff"
width="90%"><tr>
<td style="background-color:#5588cc; text-align:center; color:#fff">Geef
uw mening!</td>
</tr><tr>
<td>
<table border="0" cellpadding="2" cellspacing="0" width="100%"><tr>
<td colspan="4" align="center"><b>Wat vindt u van deze site? [totaal
<span id="totalen">??</span> stemmen]</b></td>
</tr><tr>
<td colspan="4"> <!-- Lege regel --></td>
</tr><tr align="left" valign="top">
<td id="wrde0">??</td><td> </td>
<td id="staaf0"><img src="pixel-1.gif" id="stl0">
<span id="perc0">??</span></td><td> </td>
</tr><tr align="left" valign="top">
// Voor elke staaf herhalen
<td id="wrde5">??</td><td> </td>
<td id="staaf5"><img src="pixel-6.gif" id="stl5">
<span id="perc5">??</span></td><td> </td>
</tr></table>
</tr></table><br>
Voorbeeld van een Staafdiagram.
</div>
Downloaden:
Druk op de knop:
File: voorb825.zip, 2586 bytes.
Opmerking:
Een versie voor kolomdiagrammen is te vinden het item Kolomdiagrammen met animatie.
