Three.js Scroll Seasons Tree — Keyframe Color Grading

Three.js Scroll Four Seasons Tree · Scroll · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Compact keyframe system: five season states, every visual property lerped between adjacent pairs
Smoothstep on the blend fraction so each season holds at its center instead of perpetually transitioning
Winter as foliage scale 0.12 — the tree visibly sheds and regrows leaves through the same lerp
One 400-point recycled particle system playing blossoms, leaf-fall, and snow via keyframed color/opacity
Cube-root radial puff distribution fills the crown evenly instead of clustering at the center
Keyframed sun color and intensity: the same geometry reads lush in summer, skeletal in winter
Half-orbit camera giving each season its own viewing angle, plus clock-driven crown rustle
Cyclical structure — the fifth keyframe duplicates spring so the scroll ends where it began

About this UI Snippet

How to Build a Scroll-Driven Four Seasons Tree With Three.js and GSAP

Screenshot of the Three.js Scroll Four Seasons Tree snippet rendered live

The Three.js Scroll Four Seasons Tree snippet plants a low-poly tree on a hillside disc and lets one scroll carry it through an entire year — spring blossoms drifting past green buds, deep summer foliage, orange autumn leaf-fall, bare branches under snow, and back to spring — while the camera circles the tree a half-turn. The engine underneath is a compact keyframe system: five season states, one scrubbed year value, and everything on screen lerped between adjacent keyframes.

Seasons as data: the keyframe table

Every visual property that changes across the year lives in one array of keyframe objects: sky color, ground color, foliage color, light color and intensity, foliage scale, particle color, and particle opacity, plus a HUD name and accent. The frame loop computes which pair of keyframes the year progress falls between (seg = p × 4), and lerps every property by the fractional part. Adding a fifth visual property to the year means adding one field to five objects — no animation code changes. The fifth keyframe duplicates spring, so the year closes its loop and the scroll's end matches its beginning, a cyclical structure unlike the linear arcs of the ocean dive or planet approach.

Smoothstep holds each season at its center

Raw linear blending would keep the scene perpetually in transition — always between seasons, never *in* one. Passing the blend fraction through smoothstep (f²(3 − 2f)) flattens the curve near 0 and 1, so each season visibly holds near its keyframe before easing into the next. One line converts a continuous color wash into four distinct acts with transitions.

Winter is a scale, not a texture swap

The foliage is 90 icosahedron puffs distributed through the crown by a cube-root radial distribution (which fills a sphere evenly instead of clustering at the center). Their season behavior is driven by two lerped values: color (bud green → deep green → orange → snowy white) and scale — and winter's scale keyframe is 0.12, which shrinks the puffs to almost nothing and reveals the branch skeleton underneath. Shrinking beats hiding: the tree visibly *loses* its leaves through late autumn and buds them back through early spring, both directions handled by the same lerp. Each puff also breathes ±3% on clock time with a per-puff phase, so the crown rustles while scroll is idle.

One particle system plays three roles

Pink blossom petals in spring, orange falling leaves in autumn, white snow in winter — all the same 400-point recycled system. The keyframes drive its color and opacity (summer sets opacity 0, turning it off entirely), while per-particle seeds vary fall speed and sway. Points wrap from ground back to the sky, the recycle pattern this series uses everywhere from starfield warp onward. One system, three seasonal meanings, zero allocation.

A half-orbit that pairs with the year

The camera circles the tree just over half a turn across the scroll, so each season also gets its own viewing angle — and because sun color and intensity are keyframed too, the same geometry reads warm and lush in summer light and cold and skeletal under the dim winter sun. The HUD swaps the season name and its accent color at each blend midpoint. Scrolling backwards runs the year in reverse, snow lifting off and leaves reattaching, since every property derives from the single scrubbed value — the same guarantee behind the tornado vortex's dispersal.

Build with AI

Build, Understand, Optimize, and Extend It With AI

You do not need to design a keyframe interpolation system from scratch — this snippet is one, in about thirty lines. Paste its HTML, CSS, and JS into an AI assistant like Claude and ask it to explain the segment/fraction indexing, why smoothstep creates distinct seasons, or how winter works as a scale keyframe. The same assistant can grow the scene — a second smaller tree with offset timing, keyframed fog for autumn mist, day-night as a second orthogonal keyframe track blended with the seasons, birds that appear only in the spring and summer segments, or your brand's palette swapped into the K table in one pass. It can also refactor the keyframe walker into a reusable function you feed any property table. Treat the code as a starting point to interrogate and reshape, not a finished artifact.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a "scroll-driven four seasons tree" in plain HTML, CSS, and JavaScript using Three.js and GSAP's ScrollTrigger plugin, all loaded from a CDN (no bundler, no build step).

Requirements:
- A pinned full-viewport section with a canvas, WebGLRenderer, PerspectiveCamera (resized with aspect on window resize), ambient light, and one DirectionalLight sun whose color AND intensity will be keyframed.
- A low-poly tree: cylinder trunk, ~6 tilted cylinder branches placed around it with seeded randomness (sin-hash, no Math.random), and ~90 icosahedron foliage puffs distributed through the crown using a cube-root radial distribution for even sphere filling.
- A CircleGeometry ground disc whose color is keyframed with the seasons.
- A keyframe array of FIVE season states (spring, summer, autumn, winter, spring again for wraparound), each holding: sky color, ground color, leaf color, light color, light intensity, foliage scale (winter ≈ 0.12 so branches bare out), particle color, particle opacity (summer = 0), a season name, and a HUD accent color.
- One GSAP tween (ease "none") scrubbing year progress 0→1 on a ScrollTrigger with pin: true, scrub ~0.5, end ~+=500%.
- Each frame: seg = p × 4, take keyframes K[floor(seg)] and K[floor(seg)+1], blend fraction = smoothstep(frac(seg)), and lerp EVERY property — scene.background, ground color, sun color/intensity, puff color and scale, particle color/opacity. No season logic outside the table.
- One recycled 400-point particle system falling from sky to ground and wrapping, with per-particle seeded speed and sway — it must read as blossoms (pink), leaf-fall (orange), and snow (white) purely through the keyframed color/opacity.
- Puffs breathe ±3% on clock time with per-puff phase; camera orbits just over half a turn across the scroll at radius ~30, lookAt the crown.
- A HUD showing the nearer keyframe's season name and accent color, and an intro overlay fading at p > 0.02.
- Confirm reverse scrolling runs the year backwards — snow lifting, leaves reattaching — with no one-shot events.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Load the three CDN scriptsAdd three.min.js, gsap.min.js, and ScrollTrigger.min.js in that order before the snippet JS.
  2. 2
    Paste HTML, CSS, and JSA low-poly tree in fresh spring green stands on a hill disc, pink blossom petals drifting, the HUD reading SPRING.
  3. 3
    Scroll through summerFoliage deepens and swells, petals stop, light warms and brightens as the camera begins its half-orbit.
  4. 4
    Enter autumn and winterThe crown turns orange as leaves fall, then puffs shrink to bare branches while snow drifts down under cold dim light.
  5. 5
    Close the loopThe final quarter blends winter back into spring — the year ends where it began.
  6. 6
    Retheme the yearEdit the K keyframe array — every color, light level, foliage scale, and particle behavior for each season lives in one object per season.

Real-world uses

Common Use Cases

Seasonal campaign and holiday pages
One asset covers a whole year of campaigns — pin copy per season with scroll pin steps and land the CTA in the season you are selling.
Growth and lifecycle storytelling
Nonprofits, gardens, and sustainability brands get the literal metaphor: plant, flourish, shed, rest, return.
Teaching keyframe interpolation
A clean, visual introduction to keyframe tables, segment indexing, and why smoothstep beats linear blends — transferable far beyond Three.js.
Ambient hero for calm brands
Wellness, tea, and stationery brands can idle on any season — the rustling crown and drifting particles keep it alive, gentler than a tornado vortex.
Generative art and poetry pages
Pair each season with a stanza; the reverse scroll reading (winter back to spring) becomes part of the piece.
Farming and cozy game promos
Stardew-adjacent games can preview their season cycle in one scroll, then hand off to a scroll horizontal gallery of screenshots.

Got questions?

Frequently Asked Questions

Through a keyframe table: five state objects (spring, summer, autumn, winter, spring-again) each hold sky, ground, foliage, and light colors, light intensity, foliage scale, and particle color/opacity. The frame loop maps progress to a segment (p × 4), takes the adjacent keyframe pair, and lerps every property by the smoothstepped fraction. The seasons are data; the animation code never mentions any season by name.

Scale is continuous, visibility is binary. With winter's foliage scale keyframed at 0.12, the autumn→winter blend shows the crown gradually thinning to bare branches, and winter→spring shows buds swelling back — both directions for free through the same lerp. Toggling visible would snap 90 puffs off in one frame, which reads as a glitch rather than a season.

The falling behavior is identical — only color, opacity, and size differ, and those are keyframed like everything else: pink at 0.9 opacity in spring, off (0.0) in summer, orange in autumn, white in winter. Per-particle seeds vary drop speed and sway so the field never looks uniform. One geometry, one material, one draw call, three seasonal meanings.

Linear blending means the scene is at a 50/50 color mix through the middle of every segment — the year reads as one long crossfade. Smoothstep (f²(3−2f)) has near-zero slope at both ends, so the scene sits close to each pure keyframe for a good portion of its segment and moves through the mix quickly. Four distinct seasons with transitions, rather than four transitions with no seasons.

Yes. Export via the JSX, Vue, Angular, or Tailwind buttons. Build the tree, keyframe table, and ScrollTrigger in a mount effect against a canvas ref; update the HUD season name through a ref since it changes during scrub. On cleanup kill the ScrollTrigger, dispose trunk, branch, puff, ground, and flake geometries/materials, and call renderer.dispose().