# 墨池 Inkpond
> Inkpond is an ink-wash background library for web developers: animated Chinese glyphs behind your page that answer the pointer, give an empty landing, sign-in or AI chat screen some atmosphere, and stay out of the content's way.
墨池(Inkpond)是给网页开发者用的背景库:在页面背后铺一层会回应鼠标的水墨汉字动画,让空白的首页、登录页或 AI 对话页有东方意境,又不遮挡内容、不拖慢页面。
Version 0.1.0, updated 2026-10-29. Source: https://github.com/shin4/inkpond. Site: https://shin4.github.io/inkpond/
Chinese characters, laid out by stroke density, become a picture: distant hills in mist, a lotus pond with koi, a slowly unrolling handscroll of *Along the River During the Qingming Festival*, the twenty-four solar terms, changing with the date, a deep sea with a whale passing beneath it, or a very fat whale guarding a bowl of rice. The pointer stirs ripples, a click drops ink that spreads and fades, and page content keeps a clear zone around it.
- **Six scenes**: hills, lotus pond, the Qingming scroll, the 24 solar terms that follow the date, a whale in the deep sea, and a silly fat whale, with optional pale colour
- **Responsive**: ripples follow the pointer, clicks drop ink, koi flee and come to feed, walkers scatter from the ink, the whale dives when touched, the fat whale laughs when poked
- **Out of the way**: content gets a clear zone, and koi, boats and walkers steer around it
- **Light**: Canvas 2D, zero runtime dependencies, under 2 ms of script per frame, steps down on weak devices
- **React optional**: an `` component, or use it without React
## Scenes
| `scene` | Picture | What moves |
| --- | --- | --- |
| `shanshui` (default) | Two ranges of distant hills, mist drifting past | The mist |
| `lotus` | A lotus pond seen from above: leaves, flowers, duckweed | Koi swim around content, scatter from the pointer and come to where ink drops |
| `qingming` | The Qingming handscroll: mountains and city walls, a pagoda and gate towers, taverns along both banks, a timber rainbow bridge across the river | The scroll unrolls to the left, boatmen pole, walkers cross the bridge, ink scatters them |
| `jieqi` | The 24 solar terms (节气), one picture each; by default the term today falls in | See the table below; if the page stays open into the next term, it bleeds over to it in ink |
| `beiming` | 北冥, the northern deep: the open sea from above, a whale's shadow under the swell | The whale glides by, rising and sinking about once a minute and leaving flat calm footprints when shallow; touched by the pointer it dives, and ink draws it near |
| `dafeijing` | 大肥鲸, the big fat whale: a round whale and a bowl of white rice in a corner; the rice is bare paper, with a few 米 along the top of the heap | When hungry it swims over and buries its face in the bowl: rice flies into its mouth, the heap goes down and the whale swells. Full, it burps, spouts rice from its blowhole and goes flat again while the bowl refills. Ink scatters rice for it to chase, and a poke squashes it, wobbles it and makes it laugh 哈 |
The lotus, Qingming, solar-term, whale and fat-whale scenes use a touch of pale colour (vermilion, rouge, ochre, indigo); set `tint={false}` for ink only.
### The 24 solar terms
`scene="jieqi"` finds today's term from the sun's ecliptic longitude (to within about a quarter of an hour). Pin one with `term`, or show a given day's with `date`:
```tsx
// today's term, following the clock
// Frost's Descent only
// that day's term (Major Cold)
```
`jieqiAt(date)` returns the `term` a moment falls in, and `JIEQI` lists all 24 (`id`, name, longitude).
| Term | `term` | Picture | On a click / the pointer |
| --- | --- | --- | --- |
| 立春 Start of Spring | `lichun` | Ice cracks open from a point; sprouts (芽) push up along the cracks | The ink starts a new crack |
| 雨水 Rain Water | `yushui` | Slanting 雨 rain rings the water below | The pointer sets the wind |
| 惊蛰 Awakening of Insects | `jingzhe` | Lightning splits the frame with a flash; 虫 insects are thrown from the ground | Lightning strikes the ink |
| 春分 Spring Equinox | `chunfen` | Half day, half night, split by a living vermilion seam that swallows cross | The seam follows the pointer |
| 清明 Clear and Bright | `qingming` | Willow strands sway; a vermilion kite; drizzle | The pointer parts the willows |
| 谷雨 Grain Rain | `guyu` | Peonies open in layers; petals drift in the rain | A new flower opens at the ink |
| 立夏 Start of Summer | `lixia` | Frog croaks ring out and interfere | Frogs croak faster near the pointer; the ink rings too |
| 小满 Grain Buds | `xiaoman` | Waves roll through the wheat | The wheat bows under the pointer |
| 芒种 Grain in Ear | `mangzhong` | A vermilion planting line sweeps the paddy, leaving rows of seedlings | The line moves to the ink |
| 夏至 Summer Solstice | `xiazhi` | A vermilion sun with turning rays; heat shimmer on the ground | The sun drifts after the pointer |
| 小暑 Minor Heat | `xiaoshu` | Heat rises in warped plumes; cicadas call | A cool breeze at the pointer |
| 大暑 Major Heat | `dashu` | Fireflies wander over night grass, trailing light | Fireflies gather to the pointer |
| 立秋 Start of Autumn | `liqiu` | An empty frame; one leaf (叶) falls into the water | The pointer blows the leaf aside |
| 处暑 End of Heat | `chushu` | A turbulent front pushes the vermilion heat off the frame; a hawk circles | Cooling at the pointer |
| 白露 White Dew | `bailu` | Dew beads swell on the grass, then run down | A touched bead runs |
| 秋分 Autumn Equinox | `qiufen` | A full moon halved by a slowly turning vermilion diameter | The diameter points at the pointer |
| 寒露 Cold Dew | `hanlu` | Geese fly in a skein that shifts between the 人 and 一 formations; chrysanthemums below | The skein avoids the pointer |
| 霜降 Frost's Descent | `shuangjiang` | Six-armed frost grows in from the edges; vermilion maple leaves fall | The pointer's warmth melts the frost |
| 立冬 Start of Winter | `lidong` | Waves slow until they freeze into ice, crack and thaw | The ink adds a wave source |
| 小雪 Minor Snow | `xiaoxue` | Sparse snow at three depths | The pointer blows the flakes aside |
| 大雪 Major Snow | `daxue` | Driving snow builds drifts on the ground | The pointer sets the wind |
| 冬至 Winter Solstice | `dongzhi` | In the longest night a vermilion 阳 pushes back the ink; a ring of 81 dots turns to plum one by one (counting the nines) | 阳 follows the pointer |
| 小寒 Minor Cold | `xiaohan` | A plum branch grows stroke by stroke and blossoms at its tips | Blossoms open at the ink |
| 大寒 Major Cold | `dahan` | Fireworks burst over a frozen grid | A firework goes up at the ink |
| Lotus | Shanshui |
| --- | --- |
|
|
|
## Install
```bash
npm i inkpond
```
The React component also needs `react` 18 or later (an optional peer dependency).
Installing the latest commit from GitHub
```bash
npm i github:shin4/inkpond
```
A GitHub install builds `dist/` on the spot:
- npm 11 notes dependencies with build scripts (`allow-scripts`) and installs anyway; if your config blocks dependency scripts, run `npm approve-scripts inkpond`.
- bun runs no dependency scripts by default and does not install a dependency's dev dependencies. Your project needs TypeScript, and inkpond must be trusted:
```bash
bun add -d typescript
bun add github:shin4/inkpond
bun pm trust inkpond
```
## Usage
### React
```tsx
import { InkPond } from "inkpond/react";
import "inkpond/inkpond.css";
```
- The canvas fills the **nearest positioned parent** and takes pointer events from it.
- Elements with `data-inkpond-avoid` get a clear zone, including ones that appear later.
- `active` says whether this view is on screen; a background tab pauses by itself.
- Other options are read once on mount; change the `key` to remount with new ones.
- The component is marked `"use client"`, so it renders straight from a Next.js App Router Server Component. For Vue and Svelte, see the [FAQ](https://shin4.github.io/inkpond/en/faq/).
### Without React
```ts
import { createInkPond } from "inkpond";
import "inkpond/inkpond.css";
const pond = createInkPond(document.querySelector("canvas.inkpond")!, {
scene: "qingming",
});
pond.setActive(false); // when this view is hidden
pond.destroy(); // on unmount
```
### Stirring the water from code
The page can ripple and drop ink itself, say a ripple per keystroke and a drop on send. Coordinates are viewport coordinates (`clientX` / `clientY`):
```ts
pond.ripple(x, y, 0.4); // one ring of waves, strength 0–1, default 1
pond.drop(x, y); // a drop of ink; refused (false) on a clear-zone element
```
In React, `pondRef` gives you the same object:
```tsx
const pondRef = useRef(null); // the InkPond type from "inkpond"
// later: pondRef.current?.ripple(x, y)
```
Both do nothing while paused, in reduced motion and on the still tier.
## Options
| Option | Default | Meaning |
| --- | --- | --- |
| `scene` | `"shanshui"` | `shanshui` / `lotus` / `qingming` / `jieqi` / `beiming` / `dafeijing` |
| `term` | today's term | `jieqi` only: show this solar term, e.g. `"qingming"` |
| `date` | now | `jieqi` only: show this day's term, and stay on it |
| `tint` | `true` | Draw pale colour; `false` for ink only |
| `active` | `true` | Whether the view is on screen; background tabs always pause |
| `strength` | `0.45` | Ink depth of the scene; ripples and ink drops are not affected |
| `waveSpeed` | `1` | Wave speed multiplier |
| `cellSize` | the tier's (16) | Glyph cell in CSS px, 12–48: the glyph size; smaller draws more glyphs and costs more; after a step down it never goes below that tier's cell (22 on lite) |
| `levels` | per scene | Glyph levels for the main ground (the hills, the water in lotus and Qingming, or the sea in beiming and dafeijing), light to dark; other glyphs need your own font; not used by the solar terms |
| `reducedMotion` | follows the system | When on, draws one still picture and ignores the pointer |
| `avoidAttribute` | `data-inkpond-avoid` | Attribute that marks clear zones |
| `avoidPadding` | `20` | Fully clear margin around those elements (CSS px) |
| `avoidFade` | `140` | Width of the fade back to full ink (CSS px) |
| `fontUrl` | the scene's subset | `null` to use the fallback fonts only |
| `fontFamily` / `fallbackFonts` | per scene / serif stack | Font name and fallbacks |
| `tierStorageKey` | `inkpond.tier` | localStorage key that remembers a step down; `null` to forget |
**Colour**: the ink is the canvas `color`, settable with the CSS variable `--inkpond-ink`; `--inkpond-alpha` is the opacity of the darkest ink. Pale colours come from `--inkpond-zhu` (vermilion), `--inkpond-yanzhi` (rouge), `--inkpond-zhe` (ochre) and `--inkpond-huaqing` (indigo). `inkpond.css` handles `prefers-color-scheme` and `.dark` / `data-theme="dark"` on ``; colours follow theme changes.
## Performance
Each glyph is rasterised once into an atlas, and every frame only copies from it. The still parts of a scene are computed once per size, and slow layers such as mist are recomputed every 4 frames.
- **Frame rate on demand**: tier rate while the water moves; about 20–24 fps when only koi, boats or the scroll move; 10 fps when only mist drifts; stops after 30 s without input and wakes on the next pointer move.
- **Three tiers**: standard (60 fps, 16px cells), lite (30 fps, 22px cells) and still. `cellSize` changes the cell: larger is cheaper, while smaller draws more glyphs by area (12px about 1.8× as many as 16px), and a stepped-down tier still keeps its own cell as the floor. Software rendering starts on still and weak devices on lite; sustained jank steps down at runtime, remembered for 30 days.
- **Accessibility**: pauses in hidden tabs; reduced motion draws one still picture; the canvas is hidden in forced-colours mode.
Measurements
Headless Chrome, 1920×1080, DPR 1.5, script time per frame as median / p95, budget 8 ms:
| Scene | Calm water | Pointer stirring the whole screen | Slow-layer recompute (every 4 frames) |
| --- | --- | --- | --- |
| Shanshui | 0.2 / 0.3 ms | 0.9 / 1.8 ms | 0.1 ms |
| Lotus | 0.2 / 0.3 ms | 1.1 / 1.9 ms | < 0.1 ms |
| Qingming | 0.7 / 0.9 ms | 1.3 / 1.7 ms | 0.2 ms |
| Beiming | 0.4 / 0.8 ms | as lotus, p95 about 0.4 ms higher | 0.4 ms |
Nearly all of it is image copies. All 24 solar-term pictures are drawn to the same budget: at most about 2,600 glyphs per calm frame at that size, about as many as Qingming. With the GPU off and CPU rasterisation, a fully stirred frame takes about 9 ms, which is what the starting tier and the step-down are for. Step-down rules: a median over the last 10 frames above 16 ms, or a frame gap over 60 ms, goes straight to still; every 60 frames, a p95 above 8 ms or a gap over 40 ms steps down one tier. The atlas is a 16-column grid (Qingming at DPR 2 is 640×1400px), well inside the 4096px texture limit of many mobile GPUs.
## Fonts
Each scene ships a subset of Source Han Serif SC Medium (SIL OFL 1.1) with only the glyphs it uses, loaded when the scene is:
| File | Glyphs | Size |
| --- | --- | --- |
| `inkpond-shanshui.woff2` | 39 | about 10 KiB |
| `inkpond-lotus.woff2` | 66 | about 16 KiB |
| `inkpond-qingming.woff2` | 101 | about 21 KiB |
| `inkpond-jieqi.woff2` | 129 | about 29 KiB (one for all 24 terms) |
| `inkpond-beiming.woff2` | 21 | about 6 KiB |
| `inkpond-dafeijing.woff2` | 27 | about 6 KiB |
The OFL forbids modified versions from using the Reserved Font Name "Source", so the subsets are renamed **Inkpond Glyphs**. The licence and a note of the changes are in `src/assets/OFL.txt`.
## Development
```bash
bun install
bun run dev # project page at http://localhost:5173/, session demo at /session/
bun run test # unit tests
bun run smoke:pack # packaging smoke test: install from the tarball and from git, then import, type-check and bundle
bun run build # library to dist/
bun run build:demo # demo pages to dist-demo/
```
After changing the glyphs any scene uses, rebuild all subsets from the original OTF (needs `bun` and `uv`; the font is in Adobe's `adobe-fonts/source-han-serif` repository):
```bash
scripts/build-font.sh path/to/SourceHanSerifSC-Medium.otf
```
The project page source is `demo/index.html`, the FAQ is `demo/faq/` and the English versions are in `demo/en/`; the build prerenders them to static HTML with structured data, next to an [llms.txt](https://shin4.github.io/inkpond/llms.txt) and the complete [llms-full.txt](https://shin4.github.io/inkpond/llms-full.txt) for AI assistants. Every push to `main` redeploys them through `.github/workflows/pages.yml`.
## Thanks
Inkpond grew from [stackedlol/ascii-sharks](https://github.com/stackedlol/ascii-sharks): a sea of characters behind the page that swims, avoids content and answers the pointer. Inkpond turns the idea into ink wash and Chinese glyphs, written from scratch without code from the original. Thanks to [@stackedlol](https://github.com/stackedlol) for the idea.
## Licence
Code under [MIT](https://github.com/shin4/inkpond/blob/main/LICENSE); the font subsets under SIL OFL 1.1, each applying separately.
## FAQ
### What is Inkpond?
Inkpond (墨池) is a web background library: a layer of animated Chinese glyphs in the style of ink-wash painting, laid behind the page. The glyphs, dense or sparse by stroke count, form distant hills in mist, a lotus pond with swimming koi, or the slowly unrolling handscroll Along the River During the Qingming Festival. The pointer stirs ripples and a click drops ink.
### Who is it for, and where does it fit?
Front-end developers and designers who want an East Asian ink-wash atmosphere on a page: product landing pages, sign-in pages, the empty start screen of an AI chat app, personal sites, portfolios and event pages, or any page with little content that needs some mood.
### What problem does it solve?
An empty landing or chat screen feels bare, while video backgrounds and large images are heavy and compete with the content. Inkpond gives the page a moving, pointer-aware background for very little (a glyph subset of 6–29 KiB per scene, no runtime dependencies) and keeps clear of the content, so text stays readable and the page stays fast.
### How do I install and use it?
Install with `npm i inkpond` (or the latest commit with `npm i github:shin4/inkpond`). Import the stylesheet with `import "inkpond/inkpond.css"`, then put `` in a React tree, or call `createInkPond(canvas)` on any canvas.
### Which frameworks does it support? Is it React only?
The core is a framework-free TypeScript library: `createInkPond(canvas, options)` works in plain JavaScript, Vue, Svelte, Angular and anything else that gives you a canvas. There is also a React component, `inkpond/react`, for React 18 and later (an optional peer dependency).
### Does it work with Next.js (App Router)?
Yes. `inkpond/react` is marked "use client", so you can render `` straight from a Server Component in the App Router; import `inkpond/inkpond.css` once (say in the root layout). Pass only plain props across the server boundary; to call `ripple()` or `drop()` from code, use `pondRef` inside a client component of your own.
```
// app/page.tsx — a Server Component is fine: inkpond/react is "use client"
import { InkPond } from "inkpond/react";
import "inkpond/inkpond.css";
export default function Page() {
return (
…
);
}
```
### How do I use it in Vue?
Use the framework-free API: create the pond when the component mounts and destroy it when it unmounts. The canvas needs the `inkpond` class (or your own sizing), and its parent must be positioned.
```
…
```
### How do I use it in Svelte?
The same pattern: create the pond in `onMount` and return its `destroy`.
```
…
```
### What scenes are there?
Six: `shanshui` (the default) is two ranges of hills in mist; `lotus` is a lotus pond whose koi flee the pointer and swim to dropped ink; `qingming` is a handscroll that keeps unrolling, with city walls, a pagoda, the rainbow bridge, boats and walkers; `jieqi` is the twenty-four solar terms, a moving picture for each that changes with the date (or pin one with `term`); `beiming` is the deep sea seen from above, with a whale's shadow that rises and sinks, dives when the pointer touches it and comes toward dropped ink; `dafeijing` is a comic big fat whale with a bowl of white rice (the rice is bare paper): it eats until it swells, burps and spouts rice, chases rice scattered where ink drops, and laughs when poked. Lotus, Qingming, the solar terms and both whales carry a touch of pale colour, or ink only with `tint: false`.
### How is it different from Vanta.js or tsParticles?
Vanta.js draws 3D and WebGL effects with three.js or p5.js, and tsParticles draws configurable particles, confetti and similar effects; both offer many presets. Inkpond does one narrower thing: an ink-wash picture made of Chinese glyphs, with scenes that avoid your content (clear zones that koi, boats and walkers steer around), on Canvas 2D with no runtime dependencies. Pick Inkpond for that East Asian ink look behind text-heavy or empty pages; pick the others for 3D or particle effects.
### Will it slow the page down or drain the battery?
Not noticeably. Each glyph is rasterised once and every frame only copies from the atlas; measured at 1920×1080 and DPR 1.5, the script takes a median of under 1 ms per calm frame, and about 2 ms at the p95 when the whole screen is stirred; the busiest solar terms cost about the same as Qingming. It lowers its frame rate when calm, stops after 30 s idle, pauses in hidden tabs, and steps down to a lite tier or a still picture on weak devices or software rendering.
### Does it cover or interfere with page content?
No. Mark content elements with `data-inkpond-avoid` and a clear zone forms around them, which koi, boats and walkers also avoid; clicks on buttons, links, inputs and other controls never drop ink. The canvas sits under the nearest positioned parent and does not affect layout.
### How does it behave on phones and touch screens?
Yes. On touch screens a dragging finger does not stir ripples (so scrolling stays smooth), and a tap on empty space drops ink. Devices with fewer cores or less memory start on the lite tier, with larger cells and a lower frame rate.
### Is it accessible?
The canvas is hidden from screen readers (`aria-hidden`); with reduced motion on, it draws one still picture; in forced-colours (high contrast) mode the canvas is hidden so text stays legible.
### Can I change the colours, the depth or the glyphs?
Yes. The ink and the four pale pigments (vermilion, rouge, ochre, indigo) are CSS variables with dark-mode values; ink depth, glyph size (`cellSize`), wave speed and the width of clear zones are options; `levels` replaces the glyphs of the main ground (other glyphs need a font that covers them).
### Can I use it commercially? What is the licence?
Yes. The code is MIT licensed: free for personal and commercial projects as long as the copyright notice stays. The bundled glyph subsets of Source Han Serif are under the SIL Open Font License 1.1, which also allows commercial use.
### Where does the font come from, and how much does it load?
From Source Han Serif SC Medium. Each scene ships only the glyphs it uses, 6–29 KiB each (the 24 solar terms share one), loaded only when that scene is. As the OFL requires, the subsets are renamed Inkpond Glyphs.
### How is it related to ascii-sharks?
Inkpond grew from stackedlol/ascii-sharks, a sea of characters swimming behind the page. Inkpond turns the idea into ink wash and Chinese glyphs and was written from scratch, with no code from the original.
## 常见问题(中文)
### 墨池是什么?
墨池(Inkpond)是一个网页背景库:在页面背后铺一层水墨风格的汉字动画。汉字按笔画疏密排成远山云雾、鲤鱼游动的荷塘,或缓缓展开的清明上河长卷;鼠标划过泛起水波,点击空白处落墨。
### 墨池给谁用?适合用在哪里?
给想让网页有东方水墨氛围的前端开发者和设计师:产品首页、登录页、AI 对话应用的空白起始页、个人主页、作品集、活动页,以及任何内容不多、需要一点氛围的页面。
### 墨池解决什么问题?
空白的首页或对话页显得冷清,而视频背景或大图又重又抢内容。墨池用很少的资源(每个场景十到三十 KiB 的字体子集,无运行时依赖)给页面一层会动、会回应鼠标的水墨背景,同时自动避开页面上的内容,不遮挡文字,也不拖慢页面。
### 怎么安装和使用?
用 npm 安装:`npm i inkpond`(也可以从 GitHub 安装最新提交:`npm i github:shin4/inkpond`)。然后引入样式 `import "inkpond/inkpond.css"`,在 React 里放一个 ``,或者用 `createInkPond(canvas)` 挂到任意画布上。
### 支持哪些框架?只能用 React 吗?
核心是不依赖任何框架的 TypeScript 库,`createInkPond(canvas, options)` 在原生 JavaScript、Vue、Svelte、Angular 里都能用。另外提供一个 React 组件 `inkpond/react`(需要 React 18 及以上,是可选依赖)。
### 能在 Next.js(App Router)里用吗?
可以。`inkpond/react` 已经标了 "use client",在 App Router 的服务端组件里可以直接写 ``;`inkpond/inkpond.css` 引入一次即可(比如放在根 layout)。跨服务端边界只能传普通的属性;想在代码里调用 `ripple()` 或 `drop()`,就在你自己的客户端组件里用 `pondRef`。
```
// app/page.tsx — a Server Component is fine: inkpond/react is "use client"
import { InkPond } from "inkpond/react";
import "inkpond/inkpond.css";
export default function Page() {
return (
…
);
}
```
### 在 Vue 里怎么用?
用不依赖框架的接口:组件挂载时创建,卸载时销毁。画布要带 `inkpond` 类名(或自己设置尺寸),父元素需要是定位元素。
```
…
```
### 在 Svelte 里怎么用?
同样的做法:在 `onMount` 里创建,返回它的 `destroy`。
```
…
```
### 有哪些场景?
有六个场景:`shanshui`(山水,默认)是两重远山与云雾;`lotus`(荷塘)是荷叶荷花,鲤鱼会躲开鼠标、游向落墨处;`qingming`(清明上河)是一卷不断展开的长卷,有城郭、宝塔、虹桥、船只和行人;`jieqi`(二十四节气)一节一画,按日期自动切换,也可以用 `term` 固定某一个;`beiming`(北冥)俯看深海,浪下一头鲸的影子时浮时沉,鼠标触到会下潜,落墨引它游近;`dafeijing`(大肥鲸)是一条搞笑的胖鲸守着一碗白米饭(饭是留白),吃到撑就打嗝喷米,落墨处撒米引它来吃,戳它会笑。荷塘、清明、节气和两条鲸带淡彩,也可以只用墨色。
### 和 Vanta.js、tsParticles 有什么不同?
Vanta.js 用 three.js 或 p5.js 做 3D、WebGL 效果,tsParticles 做可配置的粒子、彩带等效果,两者都有很多预设。墨池只做更窄的一件事:用汉字组成的水墨画面,并且会避开页面内容(留白区,鲤鱼、船、行人也会绕开),基于 Canvas 2D、零运行时依赖。想要东方水墨感、页面以文字为主或比较空时选墨池;想要 3D 或粒子效果时选它们。
### 会不会拖慢页面、耗电?
不会明显拖慢。每个字只栅格化一次,之后每帧只贴图;实测(1920×1080,DPR 1.5)静水时每帧脚本耗时中位数不到 1 ms,满屏搅动时 p95 约 2 ms;最繁忙的节气画面和清明上河相当。画面静下来会降帧,30 秒无操作就停帧;标签页隐藏时暂停;弱设备或软件渲染时自动降到轻量档或静止画面。
### 会遮挡或干扰页面上的内容吗?
不会。给内容元素加上 `data-inkpond-avoid` 属性,它周围就会自动留白,鲤鱼、船和行人也会绕开;点击按钮、链接、输入框等可交互元素时不会落墨。画布铺在最近的定位父元素下面,不影响布局。
### 手机和触屏上效果怎样?
可以用。触屏上手指滑动不会起波(避免和页面滚动冲突),轻点空白处会落墨;CPU 或内存偏弱的设备从轻量档开始,字格更大、帧率更低。
### 对无障碍友好吗?
画布对读屏软件隐藏(`aria-hidden`);系统开启「减少动画」时只画一张静止画面;高对比度(强制颜色)模式下隐藏画布,保证文字可读。
### 能改颜色、浓淡或换成自己的字吗?
可以换。墨色和四种淡彩(朱、胭脂、赭石、花青)都是 CSS 变量,支持暗色主题;浓淡、字号(`cellSize`)、水波速度、留白宽度都有选项;`levels` 可以替换主地面用的字(换字需要自备覆盖这些字的字体)。
### 可以商用吗?是什么许可?
可以。代码以 MIT 许可发布,个人和商业项目都能免费使用,保留版权声明即可。随包附带的字体是思源宋体的子集,按 SIL OFL 1.1 授权,同样允许商用。
### 字体从哪里来?要额外加载多少?
字形来自思源宋体 SC Medium(Source Han Serif),每个场景只带自己用到的字,约 6–29 KiB 一个(二十四节气共用一个),用到哪个场景才加载哪个。按 OFL 规定改名为 Inkpond Glyphs。
### 和 ascii-sharks 是什么关系?
墨池的想法来自 stackedlol/ascii-sharks:用字符在页面背后养一片会游动的海。墨池把它换成了水墨和汉字,代码从头写起,没有使用原仓库的代码。