Projekt 1: Jeges vonalak
A vonalak először is fehérek, ezért menjünk be a CSS-be, és adjunk a vászonnak sötét hátteret:
canvas {
background: linear-gradient(45deg, #0d1011 0% 20%, #163486);
}
Line Constructor
Most vissza a canvas.js
. Hozzunk létre egy új Line
osztályt:
class Line {
constructor(x, y, offset) {
this.x = x;
this.y = y;
this.offset = offset;
this.radians = 0;
this.velocity = 0.01;
}
Az egyes vonalak x
és y
pozíciójának meghatározásán kívül van még néhány tulajdonságunk, amivel érdekesebbé tehetjük a látványt:
- A
offset
tulajdonság segítségével a vonalakat egymástól változó távolságban ábrázolhatjuk. - Példánkban körkörös mozgást is fogunk használni. A
radians
tulajdonsággal meghatározhatjuk a mozgás szögét, avelocity
tulajdonsággal pedig a mozgás sebességét.
Line Draw Method
A következőkben meg akarjuk rajzolni a vonalakat. Minden vonal alján van egy kis kör, amit a arc
függvény segítségével határozhatunk meg, majd a vonal kilő a képernyő tetejére:
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
}
}
Azért, hogy teszteljük, hogy működik-e, létrehozhatunk egy mintasort:
const line = new Line(250, 800, 0);
line.draw();
100 vonal generálása
De azt szeretnénk, ha a vonalak kitöltenék a képernyőt, ezért szükségünk lesz egy módra, hogy létrehozzunk egy 100 vonalból álló tömböt. Íme egy egyszerű változat:
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)
)
);
};
Ezek a sorok megtekintéséhez ki kell váltanunk a draw
metódusaikat. Mivel hamarosan animálni fogjuk őket, a legjobb hely erre a animate
függvényben van:
function animate() {
requestAnimationFrame(animate);
c.clearRect(0, 0, window.innerWidth, window.innerHeight);
lineArray.forEach(line => {
line.draw();
});
};animate();
Most már 100 sorunk van! De érdekesebbé tehetjük a kiinduló helyzetünket: az alábbi kódban a random
változó segít finom variációt biztosítani, ami természetesebbé teszi az összhatást. (A Math.sin(i)
változót is használom, hogy némi hullámosságot adjak a kezdőpozíciókhoz. Ez nem szükséges, de szép húzás.)
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)
)
);
};
Játszadozz a számokkal, amíg meg nem találod a neked tetsző kezdőmintát!
Animáció
Innen már nagyon egyszerű hozzáadni a kívánt animációt. Menjünk vissza a Line
osztályunkhoz, majd a update
metódusban adjuk hozzá a következőket:
this.radians += this.velocity;
this.y = this.y + Math.cos(this.radians + this.offset);
Minden animációs képkockával a this.radians
this.velocity
-al fog nőni. Ezután a this.radians
-t arra fogjuk használni, hogy körkörös mozgást hozzunk létre a Math.cos
segítségével .
Ha még nem találkoztál korábban a Math.sin
vagy a Math.cos
-val (vagy a trigonometriád egy kicsit berozsdásodott!), ez nem akadályozhat meg abban, hogy kövess minket. Csak tudd, hogy a Math.cos
segítségével oda-vissza mozgást hozhatunk létre, az alábbi grafikon lila vonalával megegyező mintázatban:
Végül a this.offset
hozzáadásával a vonalak különböző szögben kezdenek hurkolásba.
Azt hiszem, hogy ez egy nagyon szép hatás. De az utolsó simításként adjunk hozzá egy kis interaktivitást. Amikor a felhasználó a vonalak fölé mozog, változtassuk meg a színüket.
Interaktivitás
A legegyszerűbb módja annak, hogy lássuk, hogy a felhasználó egere az egyik vonal fölött van-e, a canvas beépített isPointInPath
módszerének használata.
De további finomítások nélkül ez nem lesz túl hasznos. A vonalak csak 1 pixel szélesek, így a változások kiváltásának esélye túl kicsi lesz ahhoz, hogy érdekes legyen!
Egy nagyszerű megoldás erre a problémára, ha láthatatlan vonalakat hozunk létre minden egyes vonalunk mögött. A láthatatlan vonalaknak szélesebbnek kell lenniük, és ezeket használhatjuk a isPointInPath.
isPointInPath
A draw
metódusunkban hozzunk létre egy drawLinePath
nevű függvényt. Ennek egy width
-t kell kapnia a láthatatlan vonalainkhoz, és egy color
-t (amivé a látható vonalaink válnak, amikor a láthatatlan vonalak érintkeznek):
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;
};
};
(Figyeljük meg, hogy a fenti nyílfüggvények használata implicit módon megköti a megfelelő kontextust a this
-hez ).
Ezután könnyen hozzáadhatunk különböző szélességű láthatatlan vonalakat, hogy különböző színváltozásokat váltsunk ki. A következő kódnak világossá kell tennie, hogy mi történik:
drawLinePath(150, 'red');
drawLinePath(50, 'yellow');
De ha finomabb hatást szeretnénk elérni, próbáljuk ki:
drawLinePath(150, '#baf2ef');
drawLinePath(50, '#dcf3ff');
És ezzel kész!
A teljes JavaScript-kódért nézze meg ezt a gist-et.