Interaktív látványelemek készítése JavaScript és HTML5 Canvas segítségével

, Author

Projekt 1: Jeges vonalak

A legjobb eredmény érdekében nyissa meg teljes képernyőn

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, a velocity 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:

Kozinuszhullám

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.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.