Media Factory Logo
  • Build Ready
  • Produkty
  • Reference
  • Kariéra
  • Blog
  • Kontakty
Sledujte nás LinkedIn
Úvodní stránka Blog Generativní umění v HTML Canvas: když kód začne tvořit

Generativní umění v HTML Canvas: když kód začne tvořit

16. 01. 2026

Generativní umění zažívá obrovský boom. TouchDesigner nebo Resolume Wire jsou toho příkladem, pokud máte rádi no code přístup. Nejde jen o náhodně rozmíchané barvy nebo klikátka pro kreativce – je to způsob tvorby, kde hlavní roli přebírá algoritmus. Programátor dá pravidla, nastaví parametry a nechá kód, aby sám generoval tvary, pohyby a celou vizuální kompozici.

A právě HTML Canvas 2D API je k tomu překvapivě dobrý nástroj. Je v JavaScriptu/TypeScriptu, má jednoduché API a umožňuje kreslit přímo na bitmapu, takže má člověk absolutní kontrolu nad každým pixelem. Stačí pár desítek řádků JavaScriptu a vznikají hypnotické animace, organické struktury, částicové systémy nebo kompletně abstraktní obrazy, které by ručně kreslil hodiny.

Generativní umění se na webu stává platformou pro experimenty, hru s náhodou, šumem, symetrií i matematikou. A Canvas dává vývojáři přesně to, co k tomu potřebuje: volnost, rychlost (minimálně WebGL/GPU kontext, což je mimo scope tohoto článku) a čisté plátno, na které může kreslit bez omezení.

Pokud Vás baví kombinovat kreativitu a kódování, generativní umění v Canvasu je ideální vstupní brána do fascinujícího světa, kde se programovací logika mění v estetické dílo.

Linky na projekt:

https://github.com/urbik-mf/canvas-blog-project

https://stackblitz.com/~/github.com/urbik-mf/canvas-blog-project

Váš prohlížeč nepodporuje přehrávání videa.

Struktura generativní animace v Canvas 2D

Pro udržitelné generativní animace je efektivní rozdělit kód do několika vrstev: main loop, update logika, renderer, objekty a scény.

Main loop, obvykle běžící přes requestAnimationFrame(), řídí čas a orchestruje volání update a render funkcí v pravidelných intervalech.

Update obsahuje veškerou výpočetní logiku: pohyb částic, aplikaci fyzikálních sil, změnu parametrů šumu nebo transformací. Nemá nic společného s kreslením — pouze modifikuje stav objektů, což zvyšuje testovatelnost a modularitu kódu.

Renderer bere aktuální stav a vykresluje jej na Canvas. Měl by být čistý, bez mutací stavu nebo složitých výpočtů, což umožňuje snadné experimenty s různými vizualizačními technikami nebo export obrazu.

Objekty jsou jednotlivé vizuální/algoritmické prvky aplikace, které se skládají do scén, které je možné přepínat a experimentovat s více kompozicemi najednou.

Krátký příklad main loopu:


const context = canvas.getContext(‘2d’)
let lastTime = 0
function loop(time = 0) {
    const deltaTime = time - lastTime
    lastTime = time
    update(state, deltaTime);  	// logika animace
    render(state, contex);       	// kreslení
    requestAnimationFrame(loop);
}

Takové rozdělení zajišťuje konzistentní framerate, snadné ladění a modularitu pro komplexní generativní projekty.

Utility

mapRange funkce

  • hodí se na animace a postupné přechody mezi různýma numerickýma hodnotama
  • podporuje easingy

jednoduché funkce pro práci s 2D vektory

  • vzdálenost 2 bodů
  • normalizace vektorů pro určení směru
  • zjištění magnitudy vektoru
  • převod úhlu na normalizovaný vektor

TinyColor knihovna

  • pro manipulaci s barvami
  • přechod mezi odstíny barev
  • HSL notace je velmi užitečná

perlin/simplex noise knihovna

Hodí se například pro

  • náhodný pohyb
  • efekt oblak (lze animovat přidáním 3. rozměru a procházením skrz osu Z)
  • flow fields

sceneManager modul

  • zapínání a vypínání různých scénářů
  • lze namapovat například na tlačítko v UI či tlačítko na klávesnici pro minimální vizuální smog
  • eventy pro start, konec a tick scénáře

3D kontext a performance

Nutno dodat, že 2D kontext není příliš svižný na výpočet. Pro komplexnější vykreslování je mnohem lepší využít WebGL (případně novější WebGPU kontext), který využívá glsl shaderů pro mnohem optimálnější výpočty na GPU - má mnohem lepší paralelizaci výpočtů. Pro ulehčení práce s 3D grafikou a shadery je tu například známá knihovna three.js, která spoustu práce řeší za vývojáře.

Odlehčit performance lze i pomocí OffscreenCanvas či WebWorkerů. OffscreenCanvas se nachází ve WebWorker kontextu a lze na něj kreslit mimo hlavní vlákno, ale neobsahuje všechny možnosti 2D kontextu jako například velmi užitečné globalCompositeOperation. WebWorker bez OffscreenCanvasu lze použít zase na paralelizaci výpočtů náročných update operací - rozložit je na více vláken procesoru. V mém případě je ale největší zátěž renderovací a mám problém najít správnou cestu mezi výkonem a efekty - například velmi užitečný shadowBlur efekt je velmi náročná operace, zvlášť na velkém množství objektů.

Další techniky optimalizace můžou být například prerendering výpočetně náročného objektu na jiný canvas (který ani nemusí být v DOMu) a přepoužívání ho na více místech jako bitmapy či několik na sobě daných průhledných canvasů na které se může renderovat s menší snímkovou frekvencí, případně jen při změně nějakého stavu. Vrstvy canvasů je na sebe možno blendovat CSSkem či používat CSS filtry jako blur. Pro použití lepších efektů a náročnějších operací je ale třeba mít na paměti, že 2D kontext canvasu opravdu není performativní a pokud by tvůrce zamýšlel jejich použití pro široké publikum, je potřeba to dobře otestovat nebo v lepším případě použít WebGL/GPU.

Náš příklad

Jako příklad jsem napsal menší projekt ve vanilla TS, kde využívám některé principy z článku. Na začátek upozorním, že rendering je v tomto případě poměrně náročný a mohl by se na slabších počítačích sekat. Proto je tam tlačítko na zapnutí a vypnutí “glitch” efektu, který je poměrně náročný na rendering.

Vytvořil jsem několik scén, které se posunují UI tlačítkem. SceneManager má několik parametrů - ID, start event a kontext. Pomocí ID se teoreticky můžou vypínat a zapínat ve start eventu některé scény, ale v tomto případě je možné mít aktivní pouze jednu scénu. Možno použít pro podmínku v kódu určenou pouze pro jednu konkrétní scénu. Start event připravuje data pro scénu - vodu, sluneční grid, čtverce. Kontext zase pomocí parametrů upravuje scénu - například zapíná rendering fraktálů či backgroundu.

Main loop probíhá kontinuálně, nemá žádnou větší optimalizaci například pro neaktivní tab. Proto by bylo lepší použít například GSAP.Ticker. Hlavní renderovací jednotka je square. Square se definuje pozicí, rozměry, počtem linek a délkou linek. Pak se samostatně renderuje ještě úvodní text a background pro hlavní scénu.

Projekt je nastaven tak, že se na začátku renderu nemaže celá scéna, pouze se ztmaví - tím je zapříčiněno, že glitch efekt nezmizí úplně, ale lehce se nabaluje. Ve většině případů je ale lepší využít ctx.clearRect(0, 0, canvas.width, canvas.height) a každý frame kreslit od začátku.

Defaultní zobrazení je bez glitch efektu - ten je nutné zapnout tlačítkem nad scénou.

Scény

čtverec

  • vytvoření dat jednoho čtverce
  • čtverec se renderuje pomocí několika náhodných čar různých barev na pozici a rozměrech čtverce
  • čtverce před vykreslením transformují plátno, aby to vypadalo, že se v čase mění (scale/rotation)

grid čtverců

  • využití gridu čtverců pro multiple rendering

fraktály

  • fraktálovité útvary se zapínají pomocí kontextu stejně jako background
  • ve start eventu se mažou předchozí data ze squares pole, aby se přestali vykreslovat
  • fraktálovité útvary jsou hardcoded - nemají vlastní datovou strukturu
  • tyto útvary se vykreslují pomocí aditivní strategie transformace plátna - pokud se plátno jednou transformuje (scale, rotation, translate), tak tak zůstane dokud se netransformuje jinak. Tímto způsobem je jednoduše možné například postupně snižovat scale aniž by se musel v aplikaci držet aktuální stav plátna, tento stav si drží 2D kontext canvasu sám.

broučci

  • tato technika je fyzikální simulací, kdy se využívá pseudo chaos k tvorbě dynamického prostředí
  • vytvoří se několik částic, které se odpuzují, vloží se do ohraničeného prostoru a pak pro větší dynamičnost se některé částice nechají zmizet či objevit a tím náhodně interagují s ostatními částicemi a vznikne nekonečný chaoticky pohyb.

slunce

  • nejprve se vytvoří grid neviditelných částic (čtverec s hranou 0 a počtem čar 0)
  • do tohoto čtverce se začnou promítat kruhy
  • každý kruh má nějaké souřadnice a rádius, který narůstá
  • pokud je nějaký bod v kratší vzdálenosti od rádiusu kruhu, tak se mu proporcionálně zvedne hrana a počet vykreslujících čar
  • ve skutečnosti se kruh nevykresluje, pouze se zvětšují a změnšují pevně dané body gridu na souřadnicích které blízké kružnici

Další příklady

Pomocí techniky „fyzikálních“ částic nebo techniky vln na gridu jsem vytvořil tyto animace.  

Váš prohlížeč nepodporuje přehrávání videa.
Váš prohlížeč nepodporuje přehrávání videa.
Váš prohlížeč nepodporuje přehrávání videa.

Podívejte se na Youtube.

Jakub Urbanec

Jakub Urbanec
LinkedIn

Další články

MEDIA FACTORY Czech Republic a.s.
Green Park Offices
Žerotínova 32
130 00 Praha 3 - Žižkov

Kontaktujte nás

  • Telefon: +420 226 216 616
  • E-mail: info@mediafactory.cz

Sledujte nás

LinkedIn Instagram

Jsme členem
MEDIA FACTORY GROUP

Ochrana osobních údajů