Efekt plazmy to klasyczny efekt graficzny, kt贸ry polega na tworzeniu p艂ynnych, kolorowych animacji przypominaj膮cych wiruj膮ce chmury lub p艂omienie. W tym tutorialu nauczysz si臋, jak stworzy膰 taki efekt od podstaw u偶ywaj膮c czystego JavaScript i elementu <canvas>.
Krok 1: Struktura HTML
Zacznijmy od podstawowej struktury HTML z elementem canvas:
<canvas id="plasmaCanvas" width="400" height="400"></canvas>
Krok 2: Inicjalizacja Canvas
Pierwszym krokiem jest uzyskanie kontekstu 2D canvas oraz przygotowanie bufora pikseli:
const canvas = document.getElementById('plasmaCanvas');
const ctx = canvas.getContext('2d');
const width = canvas.width;
const height = canvas.height;
// Tworzymy obiekt ImageData do manipulacji pikselami
const imageData = ctx.createImageData(width, height);
const data = imageData.data; // Tablica RGBA pikseli
data zawiera warto艣ci RGBA dla ka偶dego piksela. Ka偶dy piksel ma 4 elementy: czerwony, zielony, niebieski i Alpha.
Krok 3: Matematyka za Plazm膮
Efekt plazmy opiera si臋 na nak艂adaniu na siebie funkcji sinusoidalnych. Dla ka偶dego piksela (x, y) obliczamy warto艣膰 u偶ywaj膮c kombinacji funkcji sin() i cos():
function plasma(x, y, time) {
// R贸偶ne fale sinusoidalne z r贸偶nymi cz臋stotliwo艣ciami
const value =
Math.sin(x / 16.0 + time) +
Math.sin(y / 8.0 + time) +
Math.sin((x + y) / 16.0 + time) +
Math.sin(Math.sqrt(x * x + y * y) / 8.0 + time);
// Normalizujemy warto艣膰 do zakresu 0-1
return (value + 4) / 8;
}
Ka偶da z tych funkcji sinusoidalnych tworzy inny wz贸r:
sin(x / 16.0)- poziome falesin(y / 8.0)- pionowe falesin((x + y) / 16.0)- fale uko艣nesin(sqrt(x虏 + y虏) / 8.0)- koncentryczne okr臋gi
Krok 4: Mapowanie Kolor贸w
Konwertujemy warto艣膰 plazmy (0-1) na kolory RGB u偶ywaj膮c funkcji sinusoidalnych z przesuni臋ciem fazowym:
function getColor(value) {
// U偶ywamy sin() z r贸偶nymi przesuni臋ciami dla RGB
const r = Math.floor(128 + 128 * Math.sin(value * Math.PI * 2));
const g = Math.floor(128 + 128 * Math.sin(value * Math.PI * 2 + 2));
const b = Math.floor(128 + 128 * Math.sin(value * Math.PI * 2 + 4));
return [r, g, b];
}
Krok 5: Renderowanie
Teraz 艂膮czymy wszystko w funkcj臋 renderuj膮c膮:
function render(time) {
// Konwertujemy czas na sekundy i spowalniamy
time = time / 1000;
// Dla ka偶dego piksela
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
// Obliczamy warto艣膰 plazmy
const value = plasma(x, y, time);
// Konwertujemy na kolor
const [r, g, b] = getColor(value);
// Ustawiamy piksel w buforze
const index = (y * width + x) * 4;
data[index] = r; // Red
data[index + 1] = g; // Green
data[index + 2] = b; // Blue
data[index + 3] = 255; // Alpha (pe艂na nieprzezroczysto艣膰)
}
}
// Rysujemy bufor na canvas
ctx.putImageData(imageData, 0, 0);
}
Krok 6: P臋tla Animacji
Ostatni krok to stworzenie p臋tli animacji u偶ywaj膮c requestAnimationFrame:
function animate(time) {
render(time);
requestAnimationFrame(animate);
}
// Startujemy animacj臋
requestAnimationFrame(animate);
Demo: Zobacz Efekt w Akcji
Pe艂ny Kod
Oto kompletny kod 藕r贸d艂owy efektu plazmy:
const canvas = document.getElementById('plasmaCanvas');
const ctx = canvas.getContext('2d');
const width = canvas.width;
const height = canvas.height;
const imageData = ctx.createImageData(width, height);
const data = imageData.data;
function plasma(x, y, time) {
const value =
Math.sin(x / 16.0 + time) +
Math.sin(y / 8.0 + time) +
Math.sin((x + y) / 16.0 + time) +
Math.sin(Math.sqrt(x * x + y * y) / 8.0 + time);
return (value + 4) / 8;
}
function getColor(value) {
const r = Math.floor(128 + 128 * Math.sin(value * Math.PI * 2));
const g = Math.floor(128 + 128 * Math.sin(value * Math.PI * 2 + 2));
const b = Math.floor(128 + 128 * Math.sin(value * Math.PI * 2 + 4));
return [r, g, b];
}
function render(time) {
time = time / 1000;
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const value = plasma(x, y, time);
const [r, g, b] = getColor(value);
const index = (y * width + x) * 4;
data[index] = r;
data[index + 1] = g;
data[index + 2] = b;
data[index + 3] = 255;
}
}
ctx.putImageData(imageData, 0, 0);
}
function animate(time) {
render(time);
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
Eksperymenty i Modyfikacje
Teraz, gdy masz dzia艂aj膮c膮 plazm臋, mo偶esz eksperymentowa膰 z r贸偶nymi parametrami:
1. Zmie艅 cz臋stotliwo艣膰 fal
Modyfikuj warto艣ci dzielnik贸w (16.0, 8.0) w funkcji plasma(), aby uzyska膰 wi臋ksze lub mniejsze wzory.
2. Dodaj wi臋cej fal
Dodaj kolejne funkcje sinusoidalne do sumy, np.:
Math.sin(x / 32.0 - time * 0.5)
3. Zmie艅 schemat kolor贸w
Eksperymentuj z r贸偶nymi przesuni臋ciami fazowymi lub u偶yj innych funkcji do mapowania kolor贸w.
4. Zmie艅 pr臋dko艣膰 animacji
Pomn贸偶 time przez wsp贸艂czynnik, aby przyspieszy膰 lub spowolni膰 animacj臋:
time = time / 1000 * 0.5; // Spowolnienie o po艂ow臋
Fraktale - 25 linii JavaScript
Sinus scroll - 30 linii
Gra "Angry Chickens"
Animowane krzywe kwadratowe - 40 linii
Animowane konstelacje cz膮steczek - 42 linie
Eksperyment z enginem fizyki