INKPOND / 墨池ScenesUsageGitHub中文

FAQ

About Inkpond

Inkpond is an ink-wash background library of Chinese glyphs for web developers. Straight answers to the questions asked most; for the full usage see the README, and for the live scenes the project page.

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 <InkPond /> 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 <InkPond /> 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 (
    <main style={{ position: "relative", minHeight: "100vh" }}>
      <InkPond scene="lotus" />
      <h1 data-inkpond-avoid="">…</h1>
    </main>
  );
}

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.
<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from "vue";
import { createInkPond, type InkPond } from "inkpond";
import "inkpond/inkpond.css";

const canvas = ref<HTMLCanvasElement>();
let pond: InkPond | undefined;
onMounted(() => { pond = createInkPond(canvas.value!, { scene: "qingming" }); });
onBeforeUnmount(() => pond?.destroy());
</script>

<template>
  <main style="position: relative; min-height: 100vh">
    <canvas ref="canvas" class="inkpond" />
    <h1 data-inkpond-avoid>…</h1>
  </main>
</template>

How do I use it in Svelte?

The same pattern: create the pond in onMount and return its destroy.
<script lang="ts">
  import { onMount } from "svelte";
  import { createInkPond } from "inkpond";
  import "inkpond/inkpond.css";

  let canvas: HTMLCanvasElement;
  onMount(() => {
    const pond = createInkPond(canvas, { scene: "shanshui" });
    return () => pond.destroy();
  });
</script>

<main style="position: relative; min-height: 100vh">
  <canvas bind:this={canvas} class="inkpond"></canvas>
  <h1 data-inkpond-avoid>…</h1>
</main>

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.