Skip to content

mxggle/kanji-recognizer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

6 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Kanji Recognizer

A lightweight, dependency-free JavaScript library for Kanji stroke order recognition and validation using KanjiVG data.

npm version License: MIT

โœจ Features

  • ๐ŸŽฏ Accurate Recognition - Uses geometric resampling algorithm with centroid-based alignment for robust recognition
  • ๐Ÿ“ Multiple Modes - Supports Stroke-by-Stroke validation, Full Kanji check, and Free Write
  • ๐Ÿ–ผ๏ธ Image Export - Export your drawings as PNG images for AI analysis or saving
  • ๐ŸŽจ Fully Customizable - Easy to style colors, animations, and recognition sensitivity
  • โšก Lightweight - Zero dependencies, pure SVG-based rendering
  • ๐Ÿ“ฑ Mobile-Friendly - Touch-optimized with pointer events
  • ๐ŸŒ Browser Compatible - Works in Chrome, Firefox, Safari, and Edge

๐Ÿ“ฆ Installation

npm install kanji-recognizer

Or use directly in browser:

<script type="module">
  import { KanjiWriter, KanjiVGParser } from './kanji-recognizer/src/index.js';
</script>

๐Ÿš€ Quick Start

import { KanjiWriter, KanjiVGParser } from 'kanji-recognizer';

// 1. Fetch kanji data from KanjiVG
const kanjiData = await KanjiVGParser.fetchData('ๆ—ฅ');

// 2. Create a writer instance
const writer = new KanjiWriter('container-id', kanjiData, {
    width: 300,
    height: 300
});

// 3. Listen for events
writer.onCorrect = () => console.log("Correct stroke!");
writer.onComplete = () => console.log("Kanji complete!");

๐Ÿ“– API Reference

KanjiWriter

Creates an interactive kanji writing canvas.

const writer = new KanjiWriter(elementId, kanjiData, options);

Parameters

  • elementId string - DOM element ID to mount the canvas
  • kanjiData string[] - Array of SVG path strings from KanjiVG
  • options object - Configuration options (optional)

Options

{
  // Dimensions
  width: 300,                    // Canvas width in pixels
  height: 300,                   // Canvas height in pixels
  
  // Colors
  strokeColor: '#333',           // Main stroke color
  correctColor: '#4CAF50',       // Success feedback color
  incorrectColor: '#F44336',     // Error feedback color
  hintColor: 'cyan',             // Hint animation color
  gridColor: '#ddd',             // Background grid color
  ghostColor: '#ff0000',         // Next stroke guide color
  
  // Appearance
  strokeWidth: 4,                // Width of drawn strokes
  gridWidth: 0.5,                // Grid line width
  ghostOpacity: '0.1',           // Ghost guide opacity
  
  // Behavior
  showGhost: true,               // Show red guide for next stroke
  showGrid: true,                // Show background grid
  checkMode: 'stroke',           // 'stroke' (immediate), 'full' (manual), or 'free' (no validation)
  
  // Recognition (Adjustable!)
  passThreshold: 15,             // Lower = stricter (10-20 recommended)
  startDistThreshold: 40,        // Start point tolerance in pixels
  lengthRatioMin: 0.5,           // Minimum stroke length ratio
  lengthRatioMax: 1.5,           // Maximum stroke length ratio
  
  // Animations
  stepDuration: 500,             // Animation speed in ms
  hintDuration: 800,             // Hint display duration
  snapDuration: 200              // Snap-to-correct duration
}

Methods

clear()

Reset the canvas and start over.

writer.clear();
hint()

Show animated hint for the next expected stroke.

writer.hint();
animate()

Animate the complete kanji stroke-by-stroke.

await writer.animate();
setOptions(newOptions)

Update configuration options dynamically.

writer.setOptions({ 
  strokeColor: '#000',
  passThreshold: 20  // Make recognition more lenient
});
destroy()

Clean up resources and remove event listeners.

writer.destroy();
exportImage(options)

Export the current drawing as a base64 PNG image.

const dataUrl = await writer.exportImage({
  includeGrid: false,
  backgroundColor: '#ffffff'
});
// Send dataUrl to AI or save it
check()

Manually trigger evaluation of all collected strokes (only for checkMode: 'full').

const result = writer.check();
if (result.success) console.log("All strokes correct!");

Event Callbacks

writer.onCorrect = () => { /* Fired on correct stroke */ };
writer.onIncorrect = () => { /* Fired on incorrect stroke */ };
writer.onComplete = () => { /* Fired when kanji is complete */ };
writer.onClear = () => { /* Fired when canvas is cleared */ };

// Error handling
writer.container.addEventListener('kanji:error', (e) => {
  console.error('Error:', e.detail);
});

KanjiVGParser

Utilities for fetching and parsing KanjiVG SVG data.

KanjiVGParser.fetchData(char)

Fetch kanji stroke data by character.

const strokes = await KanjiVGParser.fetchData('ๆ—ฅ');
// Returns: ['M25,32...', 'M12,80...']

KanjiVGParser.parse(svgContent)

Parse raw KanjiVG SVG into stroke paths.

const strokes = KanjiVGParser.parse(svgString);

KanjiVGParser.baseUrl

Set custom base URL for KanjiVG files.

KanjiVGParser.baseUrl = 'https://example.com/kanjivg/';

๐Ÿ’ก Usage Examples

Basic Kanji Practice

import { KanjiWriter, KanjiVGParser } from 'kanji-recognizer';

// Load kanji
const kanjiData = await KanjiVGParser.fetchData('ๆ„›');

// Create writer
const writer = new KanjiWriter('practice-area', kanjiData);

// Add event listeners
writer.onCorrect = () => {
  document.getElementById('feedback').textContent = 'ๆญฃ่งฃ๏ผ';
};

writer.onComplete = () => {
  document.getElementById('feedback').textContent = 'ๅฎŒๆˆ๏ผ';
  confetti(); // Celebrate!
};

Beginner Mode (Lenient Recognition)

const writer = new KanjiWriter('container', kanjiData, {
  passThreshold: 20,        // More forgiving
  startDistThreshold: 50,   // Allow imprecise starts
  showGhost: true,          // Show guides
  hintColor: '#00ff00'      // Bright hints
});

Expert Mode (Strict Recognition)

const writer = new KanjiWriter('container', kanjiData, {
  passThreshold: 8,         // Very strict
  startDistThreshold: 25,   // Precise starts required
  showGhost: false,         // No guides
  strokeColor: '#000'       // Professional look
});

Custom Styling

const writer = new KanjiWriter('container', kanjiData, {
  width: 500,
  height: 500,
  strokeColor: '#2c3e50',
  correctColor: '#27ae60',
  incorrectColor: '#e74c3c',
  gridColor: '#ecf0f1',
  strokeWidth: 6
});

Multiple Kanji Practice

const kanjis = ['ๆ—ฅ', 'ๆœˆ', '็ซ', 'ๆฐด', 'ๆœจ', '้‡‘', 'ๅœŸ'];
let currentIndex = 0;

async function nextKanji() {
  if (writer) writer.destroy(); // Clean up previous
  
  const data = await KanjiVGParser.fetchData(kanjis[currentIndex]);
  writer = new KanjiWriter('container', data);
  
  writer.onComplete = () => {
    currentIndex++;
    if (currentIndex < kanjis.length) {
      setTimeout(nextKanji, 1000);
    }
  };
}

nextKanji();

๐ŸŽจ Demo

Check out the included demo:

cd kanji-recognizer
python3 -m http.server 8000
# Open http://localhost:8000/demo/index.html

๐Ÿ”ง Requirements

  • Modern browser with ES6 module support
  • KanjiVG SVG files (not included in npm package)

Getting KanjiVG Data

Download from KanjiVG Project:

git clone https://github.com/KanjiVG/kanjivg.git

Or use a CDN:

KanjiVGParser.baseUrl = 'https://cdn.example.com/kanjivg/';

๐ŸŒ Browser Support

  • Chrome/Edge: โœ… Latest
  • Firefox: โœ… Latest
  • Safari: โœ… 14+
  • Safari iOS: โœ… 14+
  • Chrome Mobile: โœ… Latest

๐Ÿค Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

See docs/README_REVIEW.md for development documentation.

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ™ Acknowledgments

  • KanjiVG - Kanji stroke order data
  • Inspired by Japanese language learning tools

๐Ÿ“š Related Projects

๐Ÿ› Known Issues

  • None currently! Report issues on GitHub

๐Ÿ“ˆ Roadmap

  • TypeScript definitions
  • React component wrapper
  • Vue component wrapper
  • Bundled common kanji data
  • Offline support with Service Worker
  • Haptic feedback for mobile
  • Audio pronunciation integration

๐Ÿ’ฌ Support


Made with โค๏ธ for Japanese learners worldwide

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors