Canvas 2D czy Three.js — Kiedy wybrać który

Nie każda symulacja potrzebuje WebGL. Oto pełny schemat decyzyjny, którego używam, zaczynając nową symulację — i dlaczego mniej więcej połowa z 225 symulacji na tej stronie działa na czystym Canvas 2D.

Prawdziwe pytanie

Gdy zaczynasz nową symulację, wybór między Canvas 2D a Three.js rzadko sprowadza się do pytania „co jest lepsze". Chodzi o to, czego naprawdę potrzebuje sama symulacja. Dwuwymiarowe API Canvas 2D jest zaskakująco wydajne, a wątek renderowania pozostaje na CPU — a to czasem jest dokładnie to, czego potrzebujesz, gdy Twoja fizyka też działa na CPU i wymagasz ścisłej synchroniczności.

Three.js przekazuje renderowanie do GPU poprzez WebGL. To właściwy wybór, gdy masz dziesiątki tysięcy cząstek, efekty wolumetryczne lub geometrię 3D w czasie rzeczywistym. Ale to ma swoją cenę: więcej kodu, większą zależność i wyższe koszty debugowania.

Porównanie bezpośrednie

Kryterium Canvas 2D Three.js (WebGL)
Złożoność konfiguracji 3 linijki kodu minimum ~20 linijek
Liczba cząstek (60 FPS) ~2 000–5 000 50 000–1 000 000+
Rozmiar zależności 0 KB (wbudowane w przeglądarkę) ~150 KB (rdzeń Three.js)
Własne shadery (GLSL) Niedostępne Pełne wsparcie GLSL
Renderowanie 3D Ręczna matematyka projekcji Natywny graf sceny 3D
ImageData / operacje na pikselach Szybki, bezpośredni dostęp Wymaga odczytu render targetu
Renderowanie tekstu fillText() — trywialne TextGeometry / Sprites — złożone
Interaktywność (klik/przeciąganie) Prosta matematyka współrzędnych Wymaga raycastingu
Debugowanie DevTools, breakpointy działają wszędzie Błędy GLSL są trudne do odczytania
Wydajność na urządzeniach mobilnych Akceptowalna dla małego N GPU dobrze radzi sobie z dużym N
Postprocessing (bloom, blur) Ręcznie, wolno EffectComposer + wbudowane passy

Kiedy wygrywa Canvas 2D

Wybierz Canvas 2D, gdy:

Kiedy wygrywa Three.js

Przejdź na Three.js, gdy:

Prawdziwe przykłady z tej strony

Spośród 225 symulacji na tej stronie mniej więcej połowa korzysta z Canvas 2D, a połowa z Three.js. Oto podział:

Dobra heurystyka: zaczynaj każdą symulację od Canvas 2D. Jeśli po działającym prototypie napotykasz barierę liczby klatek albo potrzebujesz widoku 3D — przejdź na Three.js. Dzięki temu dodasz dodatkową złożoność tylko wtedy, gdy jest naprawdę potrzebna — i zrozumiesz algorytm, zanim zaczniesz walczyć z rendererem.

Zaczynanie od Canvas 2D, migracja później

Ścieżka migracji z Canvas 2D do Three.js jest zwykle prosta, jeśli od samego początku oddzielasz logikę symulacji od renderowania. Trzymaj aktualizację fizyki w czystej funkcji, która przyjmuje stan i zwraca nowy stan. Renderer jest jedynie konsumentem tego stanu.

// Dobra struktura — renderer można podmienić
function updatePhysics(state, dt) { /* czysta logika */ return newState; }
function renderCanvas2D(ctx, state) { /* rysuje na canvasie */ }
function renderThreeJS(scene, state) { /* aktualizuje obiekty Three.js */ }

// W pętli rAF:
state = updatePhysics(state, dt);
renderCanvas2D(ctx, state);  // podmień na renderThreeJS, gdy będziesz gotowy

Pułapka, której należy unikać: mieszanie obliczeń fizycznych z wywołaniami rysowania. Gdy tylko zrobisz ctx.moveTo(particle.x += vx * dt, ...) wewnątrz pętli rysowania, migracja zamienia się w pełne przepisanie zamiast prostej podmiany renderera.

Lista kontrolna decyzji