Cinematic websites|INEMA.CLUB-PRO

Lesson 4 · 15 min

Depth with Three.js without freezing the page

Video frames give you the film; Three.js gives you a scene drawn in code that changes angle as you scroll. The risk is the scene drawing nonstop, even when idle or off screen, and heating up the phone. Here you measure, in a headless Chromium, how many times the scene draws in each situation, and you watch the common mistake fail.

Start the lesson
A monitor on a dark desk showing a 3D wireframe scene with geometric shapes and a perspective grid.

In this lesson you will

  1. 1Draw on demand: only when the scroll progress has changed
  2. 2Density cap (1.5) and offscreen pause with IntersectionObserver
  3. 3Count the draws with Playwright: idle, scrolling, offscreen, and reduced motion
  4. 4How much Three.js weighs on the page

Goal: measure a Three.js scene that only draws when the scroll changes, pauses off screen, and respects reduced motion.

01When the scene draws

On-demand drawing: each question is a reason NOT to draw. Click each step.

Click each block in the diagram to see what it does.

The common mistake is the tutorial loop: requestAnimationFrame calling render() 60 times a second, forever.

02The heart of the kit scene

Page kit/site-three/index.html: four rings at different depths; the camera moves with the scroll. Three.js 0.186.1 (npm, 10/19/2026), copied into vendor/.

Excerpt · kit/site-three/index.html
      // On demand: only draws when scrolling changed the progress and the scene is on screen.
      const talvez = () => {
        pedido = false;
        if (!visivel) return;
        const p = progresso();
        if (Math.abs(p - ultimo) < 1e-4) return;
        ultimo = p; desenhar(p);
      };
      const agendar = () => { if (!pedido) { pedido = true; requestAnimationFrame(talvez); } };

03Measure the draws

three-medir.mjs scrolls the page in a headless Chromium and reads window.__renders in each situation.

Terminal · measure the scene and the weight
K=~/projetos/formacao-cinema-ia-sites-v72/kit
E=${TMPDIR:-/tmp}/ensaio-sites/a4; rm -rf "$E"; mkdir -p "$E"
node "$K/scripts/servir.mjs" "$K/site-three" > "$E/url.txt" & S=$!
until U=$(cat "$E/url.txt") && [ -n "$U" ] && curl -s -o /dev/null "$U"; do sleep 0.3; done
node "$K/scripts/three-medir.mjs" "$U"; echo "saída: $?"
kill $S
python3 "$K/scripts/peso.py" "$K/site-three" | head -1
echo "three.js com gzip -9: $(cat "$K"/site-three/vendor/*.js | gzip -9 | wc -c) bytes"
Terminal · common mistake: always drawing
K=~/projetos/formacao-cinema-ia-sites-v72/kit
E=${TMPDIR:-/tmp}/ensaio-sites/a4; mkdir -p "$E"
node "$K/scripts/servir.mjs" "$K/site-three" > "$E/url.txt" & S=$!
until U=$(cat "$E/url.txt") && [ -n "$U" ] && curl -s -o /dev/null "$U"; do sleep 0.3; done
node "$K/scripts/three-medir.mjs" "${U}?sempre=1" | grep "^FALHA"; echo "saída: ${PIPESTATUS[0]}"
kill $S
Example from the repository
Chromium 156.0.8078.4 (Playwright 1.64.0)
parado 0 · rolando 30 · fora da tela 0 · reduzir 1 · DPR 1,5 (tela com densidade 3)
OK: parado 0 · rolando 30 · fora da tela 0 · reduzir 1 · DPR 1,5
saída: 0
PESO: js 2,12 · html/css 0,00 (MB)
three.js com gzip -9: 415205 bytes

Idle and offscreen: zero. With reduced motion: one frame only. The last two lines are the weight: 2.12 MB raw (unminified), 0.42 MB with gzip -9. Servers usually compress JS; JPEG barely compresses. Measure what will travel over the wire before comparing with the film.

04Video frames or Three.js?

Both fit on the same page; each does one thing well.

1. Frames

Real photo, material, hard light: what a generator or a camera does better than code.

The weight grows with the length of the film.

05Practice

Measure, break, and fix.

E1 · Measure

5 min

Run the "measure the scene and the weight" block.

Done when: The line starts with OK: parado 0 · rolando (the number of draws while scrolling varies with the machine), ends with fora da tela 0 · reduzir 1 · DPR 1,5, and saída: 0 follows.

E2 · The mistake

5 min

Run the same meter with ?sempre=1 at the end of the URL (the "common mistake: always drawing" block).

Done when: Three FALHA: desenhou … lines and saída: 1.

E3 · Your scene

20 min

Copy kit/site-three to a folder of your own and swap the rings for another shape (TorusKnotGeometry, for example) and the material color. Keep the maybe function and the density cap. Serve the folder and measure.

Done when: The three-medir.mjs in your folder answers OK: parado 0 … reduzir 1 with saída: 0.

06Lesson quiz

The explanation appears after you answer.

Question 1 of 4

The page is still, with the Three.js scene on screen. How many times per second should it draw?

07In three sentences

On demandDraws only when the progress changed and the scene is on screen.
CapDensity up to 1.5; reduced motion = one frame.
Measurewindow.__renders counted by three-medir.mjs, and the library's weight in peso.py.

Going further

Previous lessonNext lesson