Projekt 1: Ledové čáry
Nejprve jsou naše čáry bílé, takže přejděme do CSS a dejme plátnu tmavé pozadí:
canvas {
background: linear-gradient(45deg, #0d1011 0% 20%, #163486);
}
Konstruktor čar
Nyní se vrátíme k canvas.js
. Vytvoříme novou třídu Line
:
class Line {
constructor(x, y, offset) {
this.x = x;
this.y = y;
this.offset = offset;
this.radians = 0;
this.velocity = 0.01;
}
Kromě určení polohy každé čáry x
a y
máme několik dalších vlastností, které nám zpestří vizuální stránku:
- Můžeme použít vlastnost
offset
pro vykreslení čar v různých vzdálenostech od sebe. - V našem příkladu budeme také používat kruhový pohyb. K určení úhlu pohybu můžeme použít vlastnost
radians
a k určení rychlosti pohybu vlastnostvelocity
.
Metoda kreslení čar
Dále budeme chtít vykreslit naše čáry. V dolní části každé čáry je malé kolečko, které můžeme definovat pomocí funkce arc
, a pak čára vystřelí do horní části obrazovky:
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
}
}
Pro vyzkoušení, že to funguje, můžete vytvořit ukázkovou čáru:
const line = new Line(250, 800, 0);
line.draw();
Generování 100 čar
Chceme však, aby čáry vyplnily obrazovku, takže budeme potřebovat způsob, jak vytvořit pole 100 čar. Zde je jednoduchá verze:
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)
)
);
};
Pro zobrazení těchto řádků budeme muset spustit jejich metody draw
. Protože je budeme brzy animovat, nejlépe to uděláme ve funkci animate
:
function animate() {
requestAnimationFrame(animate);
c.clearRect(0, 0, window.innerWidth, window.innerHeight);
lineArray.forEach(line => {
line.draw();
});
};animate();
Máme nyní 100 řádků! Můžeme však naši výchozí pozici udělat zajímavější: v níže uvedeném kódu nám proměnná random
pomůže zajistit jemnou variabilitu, která dodá celkovému efektu přirozenější vzhled. (Používám také proměnnou Math.sin(i)
, abych do počátečních pozic přidal trochu vlnění. Není to nutné, ale je to příjemný prvek)
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)
)
);
};
Hrajte si s čísly, dokud nezískáte počáteční vzor, který se vám líbí!“
Animace
Odtud je velmi jednoduché přidat požadovanou animaci. Vraťte se do naší třídy Line
a do metody update
přidejte následující:
this.radians += this.velocity;
this.y = this.y + Math.cos(this.radians + this.offset);
S každým snímkem animace se this.radians
zvýší o this.velocity
. Pomocí this.radians
pak vytvoříme kruhový pohyb, a to prostřednictvím Math.cos
.
Pokud jste se s Math.sin
nebo Math.cos
ještě nesetkali (nebo je vaše trigonometrie trochu zrezivělá!), nemělo by vám to bránit v dalším postupu. Jen vězte, že Math.cos
nám umožňuje vytvořit pohyb tam a zpět, a to podle vzoru shodného s fialovou čarou v grafu níže:

Nakonec přidáním this.offset
, začnou čáry smyčkovat pod různými úhly.
Myslím, že je to docela pěkný efekt. Ale na závěr přidáme nějakou interaktivitu. Když uživatel najede na čáry, zařídíme, aby změnily barvu.
Interaktivita
Nejjednodušší způsob, jak zjistit, zda se uživatelova myš nachází nad jednou z čar, je použít vestavěnou metodu isPointInPath
plátna.
Bez dalších úprav to ale nebude moc platné. Čáry jsou široké pouze 1 pixel, takže šance na vyvolání nějaké změny bude příliš malá na to, aby to bylo zajímavé!“
Skvělým řešením tohoto problému je vytvoření neviditelných čar za každou z našich čar. Neviditelné čáry by měly být širší a můžeme je použít ke spuštění isPointInPath.
isPointInPath
Uvnitř naší metody draw
vytvoříme funkci s názvem drawLinePath
. Ta by měla přijmout width
pro naše neviditelné čáry a color
(ve kterou se promění naše viditelné čáry, když jsou neviditelné čáry v kontaktu):
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;
};
};
(Všimněte si, že použití šipkových funkcí výše implicitně váže správný kontext pro this
).
Můžeme pak snadno přidávat různé šířky neviditelných čar, aby se spouštěly různé změny barev. Následující kód by měl jasně ukázat, o co jde:
drawLinePath(150, 'red');
drawLinePath(50, 'yellow');
Ale pro jemnější efekt zkuste:
drawLinePath(150, '#baf2ef');
drawLinePath(50, '#dcf3ff');
A to je vše!
Pro kompletní kód JavaScriptu se podívejte na tento gist.