HTML5+JS
Effecten worden gemaakt met vanilla JavaScript op een HTML5-canvas-element. In deze sectie behandelen we de basis: vormen tekenen, tekenen met iteratie en beweging toevoegen.
Vormen tekenen
Section titled “Vormen tekenen”Voor deze tutorial gebruik ik een generiek lightscript-sjabloon:
<head> <meta description="Template"/> <meta publisher="WhirlwindFX" /></head>
<body style="margin: 0; padding: 0;"> <canvas id="exCanvas" width="320" height="200"></canvas></body>
<script> // Get the canvas element from the DOM var c = document.getElementById("exCanvas"); var ctx = c.getContext("2d");
var width = 320; var height = 200; var hue = 0;
function update() { // Code goes here window.requestAnimationFrame(update); }
window.requestAnimationFrame(update);</script>Lijnen
Section titled “Lijnen”Of u nu één lijn of meerdere lijnen gebruikt, het proces blijft hetzelfde.
- ctx.beginPath() start uw vorm
- ctx.moveTo(x, y) stelt het eerste punt in
- ctx.lineTo(x, y) stelt het volgende punt in en trekt een lijn terug naar het eerste. Gebruik meerdere lineTo’s om grotere vormen te tekenen.
- Stel ctx.strokeStyle en/of ctx.fillStyle in (als de vorm gesloten is)
- Gebruik ctx.stroke() om de lijnen te tekenen en ctx.fill() om gesloten vormen te vullen. Het is belangrijk op te merken dat tot dit punt alles hypothetisch is — er wordt niets getekend totdat deze opdrachten worden uitgevoerd.
Hier zijn drie voorbeelden met lijnen:
function update() { // One Line ctx.beginPath(); ctx.moveTo(30, 30); ctx.lineTo(30, 170); ctx.strokeStyle = "blue"; ctx.stroke();
// L ctx.beginPath(); ctx.moveTo(80, 30); ctx.lineTo(80, 100); ctx.lineTo(120, 100); ctx.strokeStyle = "blue"; ctx.stroke();
// Filled Triangle ctx.beginPath(); ctx.moveTo(130, 30); ctx.lineTo(130, 100); ctx.lineTo(170, 100); ctx.lineTo(130, 30); ctx.fillStyle = "red"; ctx.strokeStyle = "blue"; ctx.fill(); ctx.stroke();
window.requestAnimationFrame(update);}
Het is belangrijk op te letten op de tekeningsvolgorde: de gevulde driehoek wordt als laatste getekend en zou de andere twee vormen bedekken als ze op dezelfde positie stonden. Bovendien wordt de lijn in de driehoek na de vulling getekend. Als we deze stappen zouden omdraaien, zou de binnenste helft van de lijn worden bedekt door de rode vulling.
Rechthoeken
Section titled “Rechthoeken”Rechthoeken zijn eenvoudig en nuttig, met name voor de gemiddelde resolutie van een RGB-toetsenbord. Het proces is vergelijkbaar met het tekenen van lijnen — vervang de opdrachten moveTo en lineTo eenvoudig door rect(x, y, breedte, hoogte).
function update() { // Basic Square ctx.beginPath(); ctx.rect(30, 30, 75, 75); ctx.strokeStyle = "blue"; ctx.stroke();
// Filled Rectangle ctx.beginPath(); ctx.rect(125, 30, 125, 100); ctx.fillStyle = "red"; ctx.strokeStyle = "blue"; ctx.fill(); ctx.stroke();
window.requestAnimationFrame(update); }
Bogen worden getekend door een buitenste punt rond een centraal punt te roteren en kunnen worden gebruikt om volledige cirkels te maken. De boog-opdracht is ctx.arc(x, y, straal, beginhoek, eindhoek), waarbij beide hoekmetingen worden opgegeven in radialen. In tegenstelling tot rechthoeken wordt een boog getekend met de oorsprong (x, y) van de vorm in het midden van de boog.
function update() { // Half-circle ctx.beginPath(); ctx.arc(70, 100, 30, 0, Math.PI); ctx.strokeStyle = "blue"; ctx.stroke();
// 3/4 circle ctx.beginPath(); ctx.arc(140, 100, 30, 0, Math.PI * (3/2)); ctx.strokeStyle = "blue"; ctx.stroke();
// Full circle ctx.beginPath(); ctx.arc(210, 100, 30, 0, Math.PI * 2); ctx.strokeStyle = "blue"; ctx.stroke(); ctx.fillStyle = "red"; ctx.fill();
window.requestAnimationFrame(update); }
Zoals u kunt zien, worden bogen standaard met de klok mee getekend. Dit kan worden omgekeerd met een eindhoek die kleiner is dan de beginhoek, of door “true” toe te voegen als laatste argument aan de methode ctx.arc().
Tekenen met iteratie
Section titled “Tekenen met iteratie”Het met de hand tekenen van drie vormen kan gemakkelijk twintig regels code kosten, dus als u honderd vormen moet tekenen, hebben we een efficiëntere aanpak nodig. Lussen in JavaScript zijn een eenvoudige manier om taken te herhalen en kunnen ook worden toegepast op tekenen.
Hier is een voorbeeld met een for-lus om een rij geblokte vierkanten te tekenen:
function update() {
for(let i = 0; i < 8; i++){
// 1. Create rectangle path and draw the stroke for each. ctx.beginPath(); ctx.rect(i * 20, 20, 20, 20); ctx.strokeStyle = "black"; ctx.stroke();
// 2. If 'i' is even, the fillStyle is black. Otherwise it's white. if(i % 2 == 0){ ctx.fillStyle = "black"; } else { ctx.fillStyle = "white"; } // 3. Fill the shape after setting the fillStyle. ctx.fill(); }
window.requestAnimationFrame(update); }
Hier is een while-lus-voorbeeld om een geblokt raster te tekenen. Ik verander de helderheid van de zwarte vakken en de tint van de witte vakken licht in elke iteratie met behulp van sjabloon-literals.
function update() {
var i = 0;
while(i < 16){
// 1. X and Y calculations with 'row' and 'column' // This operation rounds the result down to the nearest integer. For i = (0-3) the row will be 0, for i = (4-7) the row will be 1, and so on var iRow = Math.floor(i / 4); // This operation finds the remainder after division, limiting column to the (0-3) range. var iCol = i % 4; // Multiply by the square width to find this square's x-origin var ix = iCol * 20; // Multiply by the square height to find this square's y-origin var iy = iRow * 20;
// 2. Path and stroke ctx.beginPath(); ctx.rect(ix, iy, 20, 20); ctx.strokeStyle = "black"; ctx.stroke();
// 3. If the row is even, every other square is filled black. If odd, switch the black squares. Each iteration adds a small amount of the lightness component to the black, and hue to the white. if(iRow % 2 == 0){ if(i % 2 == 0){ // 'Black' ctx.fillStyle = `hsl(1, 0%, ${5 * i}%)` } else { // 'White' ctx.fillStyle = `hsl(${10 * i}, 100%, 50%)`; } } else { if(i % 2 == 0){ // 'White' ctx.fillStyle = `hsl(${10 * i}, 100%, 50%)`; } else { // 'Black' ctx.fillStyle = `hsl(1, 0%, ${5 * i}%)` } }
ctx.fill(); i++; }
window.requestAnimationFrame(update); }
Beweging toevoegen
Section titled “Beweging toevoegen”Animaties op het canvas worden alleen beperkt door uw verbeeldingskracht en uw wiskundige kennis. Als u onzeker bent over trigonometrie of meetkunde, raden we aan wat licht onderzoek te doen om uw vaardigheden naar een hoger niveau te tillen. In de volgende voorbeelden neem ik een stilstaande cirkel en koppel ik elke mogelijke variabele aan een eenvoudige oscillerende beweging.
De gouden standaard voor oscillatie (regelmatige heen-en-weergaande beweging) is het nemen van de sin() of cosinus() van een timer. Beide bewerkingen geven een waarde terug tussen -1 en 1 voor ELKE doorgegeven waarde, zelfs als die waarde alleen maar optelt. Het enige verschil tussen de twee is dat ze licht uit de pas lopen — wanneer cos 0 is, is sin -1 of 1, en omgekeerd. We kunnen dit in ons voordeel gebruiken in deze animatie:
function update() {
// Find current time in milliseconds, then divide to slow down the animation speed let time = Date.now() / 100;
// Draw a background so the old shapes don't stick around ctx.fillStyle = "white"; ctx.fillRect(0, 0, 320,200);
ctx.beginPath();
//USE ONE EXAMPLE AT A TIME // 1st example - side to side, y is constant ctx.arc(15 * Math.cos(time) + 160, 100, 30, 0, Math.PI * 2); // 2nd example - up and down, x is constant ctx.arc(160, 15 * Math.sin(time) + 100, 30, 0, Math.PI * 2); // 3rd example - circle, x and y are variable ctx.arc(15 * Math.cos(time) + 160, 15 * Math.sin(time) + 100, 30, 0, Math.PI * 2);
ctx.fillStyle = "black"; ctx.fill();
window.requestAnimationFrame(update); }Zijdelings
Section titled “Zijdelings”
Op en neer
Section titled “Op en neer”
Volledige cirkel
Section titled “Volledige cirkel”
We hebben nog slechts een paar attributen over om in de tijd te veranderen: cirkelstraal, vulling en lijn. Ik laat de booghoeken voorlopig met rust om de vorm eenvoudig te houden, want de rest zal vrij spectaculair zijn.
function update() {
let time = Date.now() / 100;
ctx.fillStyle = "white"; ctx.fillRect(0, 0, 320,200);
ctx.beginPath(); ctx.arc(15 * Math.cos(time) + 160, 15 * Math.sin(time) + 100, 30 + 15 * Math.sin(time), 0, Math.PI * 2);
ctx.fillStyle = `hsl(${180 + 180 * Math.cos(time)}, 100%, 50%)`; ctx.fill();
ctx.strokeStyle = `hsl(${180 + 180 * Math.sin(time)}, 100%, 50%)`; ctx.stroke();
window.requestAnimationFrame(update); }
Elk attribuut van elke vorm die we tot nu toe hebben gemaakt kan in de tijd worden gewijzigd, en elke animatie die ik maak is een combinatie van de bovenstaande vaardigheden. Voor meer details over het maken van herbruikbare, efficiënte animaties, bekijk onze pagina Callbacks!