01 · Entrance
Scroll is the playhead.
Every pixel you scroll moves the camera. The footage is a stack of frames drawn to a canvas, in the same animation frame as the scroll.
Web component · GSAP · optional Lenis
flythrough plays a video's frames in step with the page scroll and pauses the story at named stops, each with its own card. This page is ordinary content: the player below sits between it and the rest.
npm install flythrough gsap
01 · Entrance
Every pixel you scroll moves the camera. The footage is a stack of frames drawn to a canvas, in the same animation frame as the scroll.
02 · Lobby
Each stop has a card like this one and a label on the bar below. Stop scrolling near a card and the player glides to its stop by itself.
Between stops, passing moments drift by.
03 · Room
Short legs are stretched and long ones tightened, so no stretch of the flight is over in a flick or drags on.
Scroll back up: it all runs in reverse.
04 · Terrace
On an upright screen the frames are cropped around a focus point you set for each stop, so the subject stays in view.
05 · Rooftops
npx flythrough frames flight.mp4 --out public/tour
The frame maker cuts any video into the frame sets and the manifest this player reads.
Make the frames once, then drop the element into any page. Children with data-stop become the cards.
npx flythrough frames flight.mp4 --out public/tour
<fly-through src="/tour/manifest.json"
stops='[{"id":"door","at":0.06,"label":"Entrance"},
{"id":"lobby","at":0.17,"label":"Lobby"}]'>
<div data-stop="door">Welcome in</div>
<div data-stop="lobby">The lobby</div>
</fly-through>
<script type="module">
import 'flythrough';
import 'flythrough/style.css';
</script>
In Astro: import Flythrough from 'flythrough/astro'.
The first stop, a rough pass over the whole flight, then whatever is nearest the visitor. The page waits behind a short loading screen.
Between two frames the canvas blends them by the fraction scrolled, so slow scrolling stays smooth with 24 fps footage.
Half a second after scrolling stops, it glides to the stop whose card is showing. Never on the content above or below.
Hand it your Lenis instance and every glide goes through it. Without, GSAP's ScrollToPlugin does the same job.
Visitors who ask for less motion get one still per stop with its card, and a page that scrolls like any other.
About 10 kB gzipped plus GSAP. No framework. An Astro component and the frame maker come with it.