DEV Community

Từ Vựng 123
Từ Vựng 123

Posted on

Building a Chinese stroke-order practice tool with hanzi-writer

Chinese characters are written in a fixed stroke order, and learners who skip it end up with slow, messy handwriting and characters that handwriting keyboards fail to recognise. When we added a handwriting practice tool for Vietnamese learners of Chinese, we used hanzi-writer, an open-source JavaScript library that animates and quizzes stroke order. This post covers the parts that took more thought than expected.

What hanzi-writer gives you

hanzi-writer renders a character as SVG from stroke data (outline paths plus a median line for each stroke). It has three modes that map nicely onto how people learn:

  1. Animate: draw each stroke in order so the learner sees the sequence.
  2. Outline + trace: show a faint outline and let the learner draw over it.
  3. Quiz: hide the character and check each stroke the learner draws against the expected median, with configurable leniency.
import HanziWriter from 'hanzi-writer';

const writer = HanziWriter.create('target', '好', {
  width: 240,
  height: 240,
  padding: 8,
  showOutline: true,
  charDataLoader: loadCharData, // see below
});

writer.quiz({
  leniency: 1.2,
  onMistake: s => console.log('wrong stroke', s.strokeNum),
  onComplete: s => console.log('mistakes:', s.totalMistakes),
});
Enter fullscreen mode Exit fullscreen mode

Self-host the stroke data

By default the library fetches character data from a CDN, one JSON file per character. For a learning site that is a lot of third-party requests, and it breaks when the CDN is slow. We serve the data files from our own static path and pass a charDataLoader:

function loadCharData(char, onLoad, onError) {
  fetch(`/hanzi-data/${encodeURIComponent(char)}.json`)
    .then(r => (r.ok ? r.json() : Promise.reject(r.status)))
    .then(onLoad)
    .catch(onError);
}
Enter fullscreen mode Exit fullscreen mode

Set long cache headers on that path; the stroke data for a character never changes.

Printable practice sheets

Learners still want paper. The classic practice grid is the 米字格 (a square with diagonal and centre guide lines). Because hanzi-writer outputs SVG, the same stroke data can be drawn into a printable grid: one row per character, the first cell solid, the next few cells as faint outlines to trace, the rest empty. Generating the sheet as SVG inside an HTML page and using @media print with @page { size: A4; margin: 12mm; } gives clean output without a PDF library.

Lessons

  • Quiz leniency matters. The default (1) can feel strict for complete beginners; raising it a little lowers frustration in the first weeks.
  • Show the stroke number on mistakes. "Wrong stroke" alone is not actionable.
  • Pair characters with their components (radicals). 好 is 女 + 子; learners remember two parts better than six loose strokes.

You can try the result, including the printable 米字格 sheets, on the Chinese handwriting practice page of Tu Vung 123 (the interface is in Vietnamese, but the writing area is self-explanatory).

Top comments (0)