Project 1: IJzige lijnen
Eerst zijn onze lijnen wit, dus laten we in onze CSS het canvas een donkere achtergrond geven:
canvas {
background: linear-gradient(45deg, #0d1011 0% 20%, #163486);
}
Lijnconstructor
Nu terug naar canvas.js
. Laten we een nieuwe Line
klasse maken:
class Line {
constructor(x, y, offset) {
this.x = x;
this.y = y;
this.offset = offset;
this.radians = 0;
this.velocity = 0.01;
}
Behalve het bepalen van de x
en y
positie van elke lijn, hebben we een paar andere eigenschappen om onze visuals interessanter te maken:
- We kunnen de
offset
eigenschap gebruiken om de lijnen op verschillende afstanden van elkaar te renderen. - We gaan ook cirkelvormige beweging gebruiken in ons voorbeeld. We kunnen de
radians
eigenschap gebruiken om de hoek van de beweging te definiëren en develocity
eigenschap om de snelheid van de beweging te bepalen.
Lijn Teken Methode
Volgende, zullen we onze lijnen willen tekenen. Er is een kleine cirkel onderaan elke lijn, die we kunnen definiëren met de arc
functie, en dan schiet de lijn naar de bovenkant van het scherm:
class Line {
constructor(x, y, offset) {
this.x = x;
this.y = y;
this.offset = offset;
this.radians = 0;
this.velocity = 0.01;
} draw = () => {
c.strokeStyle = 'rgba(255, 255, 255, 0.5)';
c.fillStyle = 'rgba(255, 255, 255, 0.3)'; c.beginPath();
c.arc(this.x, this.y, 1, 0, Math.PI * 2, false);
c.fill();
c.moveTo(this.x, this.y);
c.lineTo(this.x + 300, this.y - 1000);
c.stroke();
c.closePath(); this.update();
} update = () => {
// this is where we control movement and interactivity
}
}
Om te testen of het werkt, kun je een voorbeeldlijn maken:
const line = new Line(250, 800, 0);
line.draw();
Generating 100 Lines
Maar we willen dat de lijnen het scherm vullen, dus we moeten een manier vinden om een array van 100 lijnen te maken. Hier is een eenvoudige versie:
const lineArray = ;for (let i = 0; i < 100; i++) { const start = { x: -250, y: 800 };
const unit = 25; lineArray.push(
new Line(
start.x + unit * i,
start.y + i * -3,
0.1 + (1 * i)
)
);
};
Om deze lijnen te bekijken, moeten we hun draw
methodes triggeren. Omdat we ze binnenkort gaan animeren, is de beste plaats om dat te doen de animate
functie:
function animate() {
requestAnimationFrame(animate);
c.clearRect(0, 0, window.innerWidth, window.innerHeight);
lineArray.forEach(line => {
line.draw();
});
};animate();
We hebben nu 100 lijnen! Maar we kunnen onze startpositie interessanter maken: in de code hieronder helpt de variabele random
om subtiele variatie aan te brengen, waardoor het effect er natuurlijker uitziet. (Ik gebruik ook Math.sin(i)
om wat golving in de beginposities aan te brengen. Dit is niet nodig, maar het is een leuke touch.)
const lineArray = ;for (let i = 0; i < 100; i++) { const start = { x: -250, y: 800 };
const random = Math.random() - 0.5;
const unit = 25; lineArray.push(
new Line(
start.x + ((unit + random) * i),
start.y + (i + random) * -3 + Math.sin(i) * unit,
0.1 + (1 * i)
)
);
};
Probeer met de nummers totdat je een beginpatroon hebt dat je bevalt!
Animation
Van hieruit is het heel eenvoudig om de animatie toe te voegen die we willen. Ga terug naar onze Line
klasse, en voeg dan het volgende toe in de update
methode:
this.radians += this.velocity;
this.y = this.y + Math.cos(this.radians + this.offset);
Met elk animatie frame, zal this.radians
toenemen met this.velocity
. We zullen this.radians
vervolgens gebruiken om cirkelvormige bewegingen te maken, via Math.cos
.
Als je Math.sin
of Math.cos
nog niet eerder bent tegengekomen (of je trigonometrie is een beetje roestig!), moet dat je er niet van weerhouden om mee te volgen. Met Math.cos
kunnen we heen-en-weerbewegingen maken, in een patroon dat identiek is aan de paarse lijn in onderstaande grafiek:
Door this.offset
toe te voegen, beginnen de lijnen in een lus te lopen onder verschillende hoeken.
Ik denk dat dit een aardig effect is. Maar voor de finishing touch, laten we wat interactiviteit toevoegen. Als de gebruiker met de muis over de lijnen gaat, laten we ze van kleur veranderen.
Interactiviteit
De eenvoudigste manier om te zien of de muis van de gebruiker over een van de lijnen gaat, is om de ingebouwde isPointInPath
methode van canvas te gebruiken.
Maar, zonder verdere aanpassingen, zal dit niet veel nut hebben. De lijnen zijn slechts 1 pixel breed, dus de kans dat er veranderingen optreden is te klein om interessant te zijn!
Een goede oplossing voor dit probleem is om onzichtbare lijnen te maken achter elk van onze lijnen. De onzichtbare lijnen moeten breder zijn, en we kunnen deze gebruiken om isPointInPath.
isPointInPath
Binnen onze draw
methode, laten we een functie maken genaamd drawLinePath
. Deze moet een width
nemen voor onze onzichtbare lijnen, en een color
(die onze zichtbare lijnen zullen worden, wanneer de onzichtbare lijnen in contact zijn):
const drawLinePath = (width = 0, color) => {
c.beginPath();
c.moveTo(this.x - (width / 2), this.y + (width / 2));
c.lineTo(this.x - (width / 2) + 300, this.y - (width / 2) - 1000);
c.lineTo(this.x + (width / 2) + 300, this.y - (width / 2) - 1000);
c.lineTo(this.x + (width / 2), this.y - (width / 2));
c.closePath();
if (c.isPointInPath(mouse.x, mouse.y) && color) {
c.strokeStyle = color;
};
};
(Merk op dat het gebruik van pijl functies hierboven impliciet de juiste context voor this
bindt).
We kunnen dan gemakkelijk verschillende breedtes van onzichtbare lijnen toevoegen om verschillende kleurveranderingen teweeg te brengen. De volgende code zou duidelijk moeten maken wat er aan de hand is:
drawLinePath(150, 'red');
drawLinePath(50, 'yellow');
Maar, voor een subtieler effect, probeer eens:
drawLinePath(150, '#baf2ef');
drawLinePath(50, '#dcf3ff');
En dat was het!
Voor de volledige JavaScript code, kijk op deze gist.