Deze video bestaat uit maar één deeltje. In tegenstelling tot eerdere video’s is deze destijds in de klas opgenomen. Dat verklaat het geroezemoes dat je soms hoort. Het microfoontje hing een beetje losvast aan de laptop, waardoor je de toetsaanslagen wat te hard hoort. Excuus daarvoor.
Vraag 16.1: niet een stipje, maar eentje met puntjes enzo…
Maak een HTML pagina met een canvas (ongeveer 600 bij 600).
Schrijf een script dat op dat canvas een (niet al te groot) sterretje tekent.
Vraag 16.2: sterretjes!
Verander het script nu dat het een loop gebruikt om 20 sterretjes tekent. Gebruik de volgende functie om willekeurige coördinaten te berekenen:
function randomInteger( min, max ) { return Math.floor( Math.random()*(max-min+1) )+min }
Vraag 16.3: nog meer willekeur…
De kleuren van het canvas geef je op als strings, die CSS kleuren kunnen bevatten. Kun je nu de bovenstaande randomInteger()
functie gebruiken om willekeurige kleur te maken voor ieder sterretje? (hint: denk aan rgba(r,g,b,a) notatie van CSS)
Kun je de sterrtejes ook semi-transparant maken?
Inleiding op opgaven 16.4 en 16.5
Omdat een animatie een herhaling van tekenacties is, ligt het voor de hand om er een for- of een while-loop voor te gebruiken. Dat werkt echter niet. Probeer de volgende “poging tot animatie” uit:
<html> <head></head> <body> <canvas id="mijnCanvasje" width="500" height="300" style="border: 1px dotted black"> </canvas> <script> function drawDisc( x,y,r ) { theContext.beginPath(); theContext.arc(x,y,r,0,Math.PI*2,false); theContext.closePath(); theContext.fill(); } function startDrawing(canvasId) { var canvasElement = document.getElementById(canvasId); var drawingContext = canvasElement.getContext("2d"); return drawingContext; } var theContext = startDrawing("mijnCanvasje") var x = 100; // houdt de veranderende horizontale positie bij // doe de animatie naar rechts while( x <= 400 ) { x += 10; theContext.clearRect(0,0,500,300); // wis het canvas drawDisc( x, 100, 30 ); } </script> </body> </html>
De reden waarom dit niet werkt (dit zou ook niet werken in Flash, of in game-engines) is dat de browser z’n venster pas werkelijk her-tekent nadat het script is afgelopen.
Om de stappen van de animatie zichtbaar te krijgen moet na iedere stap het script dus even eindigen, en moet de volgende stap kort daarna door Javascript gestart worden. Dat gaat niet met een while-loop of een for-loop.
De oplossing zit ‘m in het gebruik van een functie en manier om die functie herhaaldelijk te laten starten door de browser. De functie voert één stap van de animatie uit (de inhoud van bovenstaande while-loop). Als de functie klaar is krijgt de browser de gelegenheid om het scherm te hertekenen.
Het laten starten van een javascript functie door de browser kan op twee manieren: of je functie reageert op een event (muisklik, toetsaanslag etc) plaatsvindt, of je laat je functie aanroepen zodra er een timer afgaat. We proberen ze allebei.
Vraag 16.4: stap 1, animeren met een event
Maak een button in de HTML aan. Installeer een zelfgemaakte functie voor het “onclick
” event van die button die precies doet wat er binnen de while-loop in bovenstaande code gebeurt (x
verhogen, canvas wissen, balletje tekenen) – maar dan één enkele keer. Een goede naam voor die functie zou “animatieStap
” kunnen zijn (in demo 19 heet-ie “doFrame
”).
Je hebt nu een animatie die je zelf vooruit moet helpen door regelmatig op de knop te drukken. En hoewel dat niet een geweldige user experience voor de animatie oplevert, geeft het wat inzicht in hoe het Javascript executiemodel werkt, en hoe dat invloed heeft op animaties.
Vraag 16.5: tweede stap, animeren met timer
De functie setInterval
zorgt er voor dat een functie, die jij hebt opgegeven, wordt aangeroepen met tussenpozen die jij ook hebt opgegeven. Dit levert een soort repeterende timer op, ideaal voor animaties. Belangrijk voor ons nu is dat steeds, tussen twee van die aanroepen, de browser het scherm her-tekent.
Belangrijk: In het onderstaande voorbeeld wordt ‘mijnFunctie
’ als parameter meegegeven aan setInterval()
. Je ziet dat daar dan geen haakjes achter de functienaam staan. Dat zag je eerder toen we functies installeerden voor events (zoals ‘onclick
’).
Haakjes zorgen ervoor dat de functie wordt aangeroepen. Dat willen we nu niet, we willen de functie zelf noemen, zodat we de functie zelf (code e.d.) als waarde kunnen meegeven als parameter, en niet het resultaat van de functieaanroep. En dan gebruik je dus geen haakjes.
Probeer eerst dit voorbeeld uit:
// voorbeeld van setInterval setInterval( mijnFunctie, 1000 ) // 1 keer per seconde var frameTeller = 0; function mijnFunctie() { console.log("frame-teller: ", frameTeller ) frameTeller++ }
Gebruik daarna setInterval
om de animatie van het balletje te regelen. De knop kan nu dus weg.
Je moet nu beslissen hoeveel stappen per seconde je wilt. Typische frame-rates voor computeranimaties lopen van 12 (83 milliseconden tussenpozen) tot 36 (27 milliseconden). 24 is de frame-rate voor bioscoopfilms.
Voor de bonus: Kun je de animatie zo maken dat-ie het balletje laat stuiteren? Als de bal de rand van het canvas heeft bereikt, dan verandert de richtin van de animatie.
Hint: zet de waarde die je iedere keer bij het x-coordinaat van het balletje optelt in een variabele. Als een if-statment beslist dat de rand van het canvas is bereikt, dan hoef je alleen maar die variabele te veranderen van positief naar negatief (of omgekeerd).
Meer bonus ideeen:
- Niet alleen het X-coordinaat, maar ook het Y-coordinaat animeren. En dus ook in de Y-richting stuiteren.
- Meer dan 1 balletje laten animeren.
- Kun je het zo maken dat de balletjes die tegen elkaar aankomen van kleur veranderen?