Több animáció egy oldalon
Az első néhány animáció megy, a többi feketébe vált, megfagy, vagy a konzol WebGL context-tel kapcsolatos figyelmeztetést dob. Navigáláskor egyre nő a memória.
Akkor használd, ha
- Egy rácsos / listás oldalon, ahol több Rive van, csak egy része renderelődik.
- Konzol:
WebGL: CONTEXT_LOST_WEBGL,Too many active WebGL contexts, vagy hasonló. - A memória csak nő, ahogy a felhasználók animációkkal teli oldalak között mozognak.
Mire lesz szükséged
- DevTools konzol + Memory fül.
- Tudd, hogy minden animációt te inicializálsz manuálisan, vagy
useRive/ wrapper teszi.
Két probléma, két javítás
1. probléma — WebGL context limit
A böngészők egyidejűleg 8–16 WebGL kontextust engednek (böngésző / OS / GPU szerint). Egy alapértelmezett Rive példány külön kontextust nyit. A limit fölött a legrégebbi kontextusok csendben megszűnnek, az érintett canvasok feketévé válnak.
Javítás: kapcsold be minden példányon az offscreen renderert. Így mindegyik egy közös WebGL kontextust használ.
Vanilla Web:
new Rive({
src: "/animations/card.riv",
canvas,
autoplay: true,
useOffscreenRenderer: true,
});React:
useRive({
src: "/animations/card.riv",
autoplay: true,
stateMachines: "Idle",
useOffscreenRenderer: true,
});Framer: a prebuilt Rive Framer Embed komponens ezt már beállítja. Ha sajátot írsz, tedd bele.
2. probléma — Memóriaszivárgás / kontextus-kifulladás navigálás közben
A Rive C++ objektumokat allokál WASM-on keresztül. Ezeket a JavaScript GC nem gyűjti be. Ha nem hívsz cleanup()-ot, minden SPA route-váltáskor szivárog a memória és fogy egy WebGL kontextus (offscreen-nél is őriz a példány renderer-állapotot).
Javítás: hívd a cleanup()-ot, amikor a canvas elhagyja a DOM-ot.
Vanilla Web:
function tearDown() {
r.cleanup();
}
window.addEventListener("beforeunload", tearDown);
// vagy hívd a `tearDown()`-t a routered „before navigate” hookjábólReact — a useRive automatikusan takarít unmountkor. De ha saját useEffect-ben hozod létre a Rive példányt, neked kell visszaadnod a cleanup függvényt:
useEffect(() => {
let r: any;
(async () => {
const rive = await import("@rive-app/webgl2");
r = new rive.Rive({ /* ... */ });
})();
return () => r?.cleanup();
}, []);Framer: a prebuilt komponens kezeli a takarítást a useEffect return-jében.
Ugyanazt a .riv fájlt használd több canvashez
Ha a ugyanaz az animáció jelenik meg sok kártyán, töltsd le egyszer, és használd újra:
import { Rive, load } from "@rive-app/webgl2";
const file = await load(new Request("/animations/card.riv"));
for (const canvas of document.querySelectorAll(".card-canvas")) {
new Rive({
rivFile: file, // megosztva
canvas,
autoplay: true,
stateMachines: "Idle",
useOffscreenRenderer: true,
});
}Így spórolsz sávszélességet és parse-időt. Minden példánynak megmarad a saját állapota.
Késleltetett betöltés — csak akkor inicializálj, ha látszik
Hosszú oldalakon ne inicializáld a képernyőn kívüli animációkat:
const observer = new IntersectionObserver((entries) => {
for (const entry of entries) {
if (!entry.isIntersecting) continue;
initRive(entry.target.querySelector("canvas"));
observer.unobserve(entry.target);
}
});
document.querySelectorAll(".rive-card").forEach(el => observer.observe(el));Gyakori hibák
- Nem állítod be a
useOffscreenRenderer: true-t minden olyan animáción, ami másokkal együtt is megjelenhet. Az első 8–16 megy, a többi fekete. - Elmarad a
cleanup()SPA-navigáláskor vagy komponens-unmountkor. Memória és kontextusok szivárognak a látogatások között. - Lista-renderelésben kulcsok nélkül hozol létre példányokat (React). A komponensek minden re-renderkor remountolnak — a régi példányok sosem takarítanak.
- A
useOffscreenRenderercsak némelyik példányon van bekapcsolva — a többi külön kontextust foglal, és kiszorítja a többit.
Ha elakadsz, ezt küldd a Lupiannak
- Egy oldal URL-jét több példánnyal.
- Egy rövid felvételt arról, mikor szakad meg.
- A hiba körüli konzolkimenetet (keress rá:
WebGL,context). - A teljes lista: Kérj segítséget a Lupiantól.
Kapcsolódó
- Vanilla Web recept
- React / Next.js recept
- Beágyazási lehetőségek
- Részletes referencia: rive.app/docs

