68 lines
3.3 KiB
Markdown
68 lines
3.3 KiB
Markdown
# Illustrated Manuscript
|
|
|
|
An interactive illuminated manuscript page featuring an animated dragon that follows your cursor, breathes fire on click, and causes text to flow around it in real-time.
|
|
|
|
**[→ Live Demo](https://illustrated-manuscript.vercel.app/)**
|
|
|
|
## Overview
|
|
|
|
This project renders a medieval manuscript page on Canvas, featuring a hand-painted dragon made of sprite segments. The dragon tracks the mouse cursor with chain-physics (20 body segments with angle constraints), and clicking makes it breathe fire. Text reflows around the dragon body and fire particles each frame using [Pretext](https://github.com/chenglou/pretext)'s `layoutNextLine` API — no DOM measurements, no CSS reflow.
|
|
|
|
### Features
|
|
|
|
- **Real-time text exclusion** — text wraps around arbitrary moving shapes (dragon body + fire particles), re-laid out every frame via Pretext
|
|
- **Chain-physics dragon** — 20-segment inverse-kinematics body, hand-painted sprites, wing flapping, idle rest pose
|
|
- **Fire-breathing** — click to spawn particle bursts from the dragon's mouth; particles push and distort nearby text characters
|
|
- **Illuminated drop cap** — hand-drawn initial letter in manuscript tradition
|
|
- **Medieval aesthetic** — IM Fell English font, parchment tones, hand-painted sprites throughout
|
|
|
|
## Tech Stack
|
|
|
|
- **[Pretext](https://github.com/chenglou/pretext)** — Pure JS/TS text measurement & layout engine by [Cheng Lou](https://x.com/_chenglou). Enables laying out text without DOM reflow, line by line with variable widths
|
|
- **WebGL2 + 2D Canvas** — offscreen 2D Canvas compositing, uploaded to WebGL2 texture for display
|
|
- **Vite** — build tool
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
src/
|
|
config.js — constants, responsive layout calculations
|
|
dragon.js — dragon physics, sprite rendering, fire particle system
|
|
story.js — manuscript story text
|
|
main.js — entry point: WebGL pipeline, input, text layout, render loop
|
|
public/
|
|
dragon-sprites/ — 23 hand-painted dragon body part PNGs
|
|
fire-sprites/ — 10 fire particle PNGs
|
|
img/dropcap.png — illuminated drop cap
|
|
(IM Fell English loaded via Google Fonts)
|
|
```
|
|
|
|
## Getting Started
|
|
|
|
```bash
|
|
npm install
|
|
npm run dev
|
|
```
|
|
|
|
Open in browser. Desktop recommended — mobile support is limited.
|
|
|
|
## How It Works
|
|
|
|
1. **Text preparation**: story text is segmented and measured once via `prepareWithSegments()`
|
|
2. **Each frame**: dragon segments and fire particles generate exclusion rectangles
|
|
3. **Text layout**: for each line, available width ranges are computed by subtracting exclusion zones, then `layoutNextLine()` fills each range
|
|
4. **Fire text effect**: characters near fire particles are displaced, rotated, and color-shifted based on proximity
|
|
5. **Rendering**: everything composites on an offscreen 2D Canvas, then uploads to a WebGL2 fullscreen quad
|
|
|
|
## Credits
|
|
|
|
Created by [River Marchand (@Riyvir)](https://x.com/Riyvir), Creative Director at [Neither/Nor](https://neithernor.studio/).
|
|
|
|
Built with [Pretext](https://github.com/chenglou/pretext) by [Cheng Lou](https://x.com/_chenglou) — a pure JavaScript/TypeScript library for multiline text measurement & layout, enabling web UIs to bypass DOM measurements and reflow entirely.
|
|
|
|
> *"This little illuminated dragon is very happy about Pretext."* — [@Riyvir](https://x.com/Riyvir/status/2038093450139279426)
|
|
|
|
## License
|
|
|
|
ISC
|