- JavaScript 51.6%
- Svelte 33.7%
- CSS 12.7%
- HTML 2%
| public | ||
| scripts | ||
| src | ||
| .gitignore | ||
| AGENTS.md | ||
| CHANGELOG.txt | ||
| index.html | ||
| LICENSE | ||
| LICENSE-APL | ||
| LICENSE-FrequencyWords | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| svelte.config.js | ||
| UPSTREAM.md | ||
| vite.config.js | ||
HanziDraw
Draw a Chinese character, get its English definition. Fully offline, no accounts, no backend — a single-page Svelte 5 app with all data vendored or generated locally.
Requirements
- Node.js ≥ 20.19 (or 22.12+) and a package manager.
If npm is missing (e.g. Debian's split
nodejspackage):sudo apt install npm, or use the bundled corepack:corepack enable && corepack prepare pnpm@latest --activate.
Run
npm install
npm run dev # http://localhost:5173
Production build: npm run build, then serve dist/ with any static server
(npm run preview to check locally).
Usage
Draw in the pad (mouse, stylus, or touch). Candidate characters update after each stroke — click one to see its pinyin and English definitions. Or use the lookup box (shown before you draw) to type/paste a character or word (中国) directly — IME input works — or search by pinyin ("ren", "ren2", "rén", "nv3"; multiple syllables search words: "zhōng guó", "zhongguo"). The Stroke order button on a definition card shows an animated stroke-order diagram. Undo/Clear below the candidates.
Data
Dictionary data is pre-generated in public/data/cedict.json (single
characters) and public/data/words.json (compounds, lazily loaded on first
word lookup). To regenerate them (e.g. for a newer CC-CEDICT release):
npm run build:data
This downloads CC-CEDICT into scripts/.cache/ (or pass a local file:
node scripts/build-cedict.mjs /path/to/cedict_1_0_ts_utf-8_mdbg.txt[.gz]).
Stroke-order data (outline + median per stroke) is pre-generated per character
in public/data/strokes/<hex codepoint>.json. To regenerate:
npm run build:strokes # downloads graphics.txt from Make Me a Hanzi
Character-frequency data (public/data/freq.json) ranks pinyin search results
most-frequent-first. It is aggregated from the OpenSubtitles-derived Chinese
word list in hermitdave/FrequencyWords (MIT). To regenerate:
npm run build:freq # downloads zh_cn_50k.txt from FrequencyWords
npm test smoke-tests the recognizer and the pinyin helpers without a browser
(node scripts/test-recognition.mjs, node scripts/test-pinyin.mjs).
Project layout
index.html app entry (loads vendored hanzilookup.min.js)
vite.config.js Vite + @sveltejs/vite-plugin-svelte
src/main.js mounts the app
src/App.svelte top-level component, wires recognizer + dictionary
src/lib/ DrawingCanvas, CandidateGrid, DefinitionCard, cedict.js
src/app.css global styles
public/vendor/ vendored HanziLookupJS (GPL) — do not modify
public/data/ mmah.json (stroke data), cedict.json (generated)
scripts/ build-cedict.mjs, test-recognition.mjs
License
Original code in this repository is licensed under the GNU General Public License v3.0 or later — see LICENSE.
The project redistributes third-party code and data under their own licenses:
HanziLookupJS (GPL-3.0, public/vendor/), stroke data derived from
Make Me a Hanzi (Arphic Public License, public/data/mmah.json; license text
in LICENSE-APL), and CC-CEDICT dictionary data
(CC BY-SA 4.0, public/data/cedict.json). Read UPSTREAM.md
before redistributing.