Stwórz interaktywne wizualizacje za pomocą JavaScript i HTML5 Canvas

, Author

Projekt 1: Lodowate linie

Dla najlepszych rezultatów otwórz na pełnym ekranie

Po pierwsze, nasze linie są białe, więc wejdźmy do naszego CSS i nadajmy płótnu ciemne tło:

canvas {
background: linear-gradient(45deg, #0d1011 0% 20%, #163486);
}

Konstruktor linii

Teraz wróćmy do canvas.js . Utwórzmy nową klasę Line:

class Line {
constructor(x, y, offset) {
this.x = x;
this.y = y;
this.offset = offset;
this.radians = 0;
this.velocity = 0.01;
}

Oprócz określenia pozycji każdej linii x i y mamy jeszcze kilka innych właściwości, dzięki którym nasze wizualizacje będą bardziej interesujące:

  • Możemy użyć właściwości offset, aby renderować linie w różnych odległościach od siebie.
  • W naszym przykładzie będziemy również używać ruchu kołowego. Możemy użyć właściwości radians do określenia kąta ruchu oraz właściwości velocity do określenia prędkości ruchu.

Metoda rysowania linii

Następnie będziemy chcieli narysować nasze linie. Na dole każdej linii znajduje się małe kółko, które możemy zdefiniować za pomocą funkcji arc, a następnie linia wystrzeliwuje w górę ekranu:

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
}
}

Aby sprawdzić, czy to działa, możesz utworzyć przykładową linię:

const line = new Line(250, 800, 0);
line.draw();

Generowanie 100 linii

Ale chcemy, aby linie wypełniały ekran, więc będziemy potrzebowali sposobu na utworzenie tablicy 100 linii. Oto prosta wersja:

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)
)
);
};

Aby wyświetlić te linie, będziemy musieli wywołać ich metody draw. Ponieważ wkrótce będziemy je animować, najlepszym miejscem do tego jest funkcja animate:

function animate() {
requestAnimationFrame(animate);
c.clearRect(0, 0, window.innerWidth, window.innerHeight);
lineArray.forEach(line => {
line.draw();
});
};animate();

Mamy teraz 100 linii! Możemy jednak uczynić naszą pozycję startową bardziej interesującą: w poniższym kodzie zmienna random pomaga zapewnić subtelną zmienność, która nadaje całości bardziej naturalny wygląd. (Używam również Math.sin(i), aby dodać trochę falistości do pozycji początkowych. Nie jest to konieczne, ale jest miłym akcentem.)

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)
)
);
};

Pobaw się liczbami, aż uzyskasz wzór początkowy, który ci się podoba!

Animacja

Od tego miejsca bardzo łatwo jest dodać animację, którą chcemy. Wracamy do naszej klasy Line, a następnie dodajemy następujące elementy w metodzie update:

this.radians += this.velocity;
this.y = this.y + Math.cos(this.radians + this.offset);

Z każdą klatką animacji, this.radians będzie się zwiększać o this.velocity . Następnie użyjemy this.radians do stworzenia ruchu kołowego, poprzez Math.cos .

Jeśli nie spotkałeś się wcześniej z Math.sin lub Math.cos (lub twoja trygonometria jest trochę zardzewiała!), nie powinno cię to powstrzymać przed podążaniem za nimi. Wystarczy wiedzieć, że Math.cos pozwala nam na stworzenie ruchu w przód i w tył, we wzorze identycznym z fioletową linią na poniższym wykresie:

Fala cosinusowa

Na koniec, dodając this.offset , linie zaczną się zapętlać pod różnymi kątami.

Myślę, że jest to całkiem ładny efekt. Ale dla wykończenia dodajmy trochę interaktywności. Gdy użytkownik najedzie na linie, sprawmy, by zmieniły one kolor.

Interaktywność

Najprostszym sposobem sprawdzenia, czy mysz użytkownika znajduje się nad jedną z linii, jest użycie wbudowanej w canvas metody isPointInPath.

Ale bez dalszych poprawek nie będzie to zbyt użyteczne. Linie mają szerokość tylko 1 piksela, więc szansa na wywołanie jakichkolwiek zmian będzie zbyt mała, aby było to interesujące!

Świetnym rozwiązaniem tego problemu jest stworzenie niewidzialnych linii za każdą z naszych linii. Niewidzialne linie powinny być szersze, i możemy ich użyć do wyzwalania isPointInPath.

isPointInPath

Wewnątrz naszej draw metody, stwórzmy funkcję o nazwie drawLinePath . Powinna ona przyjąć width dla naszych niewidzialnych linii, oraz color (którą staną się nasze linie widzialne, gdy linie niewidzialne się zetkną):

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;
};
};

(Zauważ, że użycie funkcji strzałek powyżej implicite wiąże prawidłowy kontekst dla this ).

Możemy wtedy łatwo dodać różne szerokości niewidzialnych linii, aby wywołać różne zmiany kolorów. Poniższy kod powinien wyjaśnić, co się dzieje:

drawLinePath(150, 'red');
drawLinePath(50, 'yellow');

Ale, aby uzyskać bardziej subtelny efekt, spróbuj:

drawLinePath(150, '#baf2ef');
drawLinePath(50, '#dcf3ff');

And that’s a wrap!

Aby zobaczyć kompletny kod JavaScript, sprawdź ten gist.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.