如今学习中文汉字的工具越来越丰富,但要真正做到结构清晰、笔顺准确、且可供程序化使用的数据并不容易找到。Make Me a Hanzi(仓库地址:skishore/makemeahanzi)正是这样一个高质量、免费、开源的汉字数据仓库,它为开发者、学习者和教育应用提供了汉字基础数据与笔顺图形资源。
一、项目概述
Make Me a Hanzi是一个开源项目,主要目标是提供超过 9000 个常用汉字的详细数据,包括:
汉字的定义与拼音读音
每个汉字的笔画顺序向量图形数据(SVG 路径)
支持简体和繁体字符的数据集
该项目的数据可用于学习平台、书写练习应用、字典系统等各种场景。你可以访问演示网站,通过“画字”的方式查找汉字,或者直接下载数据集在自己的项目中使用。GitHub
项目主要包含两个核心数据文件:
dictionary.txt:包含汉字解释、拼音、部件分解等信息。
graphics.txt:每行包含一个汉字的 SVG 笔顺图路径数据。GitHub
二、核心数据结构与内容
1. 字典数据 ——dictionary.txt
每一行都是一个 JSON 对象,对应一个汉字,主要字段包括:
character:汉字字符pinyin:拼音列表definition:基本解释(面向第二语言学习者)decomposition:表意分解序列(IDS)etymology:字源信息(可选)GitHub
这使得开发者可以快速构建有解释、有拼音提示的应用场景,例如:
{"character":"汉","pinyin":["han4"],"definition":"Chinese (language)","decomposition":"⿰氵又"}2. 图形数据 ——graphics.txt
同样格式为逐行 JSON,每个对象包含:
strokes:SVG 路径列表,对应笔画顺序medians:表示笔画中线的路径数据,用于构建动画或笔顺展示
所有的坐标都采用统一的 1024x1024 坐标系设计,便于生成标准 SVG 图形。GitHub
三、项目用途和实用场景
这个项目的数据具有高度结构化和开放性,可在多种领域发挥价值:
汉字学习与教育
利用 SVG 笔顺路径数据,可以生成:
- 交互式笔顺练习
- 汉字书写教学动画
- 汉字认读练习系统
尤其对初学者而言,直观的笔顺动画比单纯的文字讲解更具学习效果。CSDN博客
开发应用集成
开发者可以基于该数据构建自己的应用,例如:
- 汉字搜索与查找工具
- 手写识别辅助系统
- 词典与注释工具
SVG 数据的优势在于能够在不同终端中自由渲染(Web、移动端、桌面应用均可)。
与其他生态项目整合
Make Me a Hanzi 的数据常被用作其他项目的数据来源或基石,例如:
- hanzi-writer(JavaScript 库,用于展示笔顺动画)
- 教育类 iOS / Android 应用
- 汉语词典及多语言词典(如中德字典)
四、如何开始使用
获取项目与数据
从 GitHub 克隆仓库:
git clone https://github.com/skishore/makemeahanzi.git cd makemeahanzi之后可以在项目中找到两个核心文件:
dictionary.txtgraphics.txt
文件本身是文本格式,每行都是独立的 JSON 对象,适合直接解析使用。
示例:用 Python 读取数据
importjson# 读取字典数据withopen("dictionary.txt","r",encoding="utf-8")asf:forlineinf:entry=json.loads(line)print(f"{entry['character']}:{entry.get('pinyin','')}-{entry.get('definition','')}")类似地,还可以解析 strokes 数据并用 SVG 或 Canvas 渲染笔顺图。
示例:输出逐字SVG
# generate_xiang_svg_animated.py# -*- coding: utf-8 -*-importjsonfrompathlibimportPathdeffind_char_line_index(dict_path:Path,ch:str)->int:withdict_path.open("r",encoding="utf-8")asf:foridx,lineinenumerate(f):line=line.strip()ifnotline:continueobj=json.loads(line)ifobj.get("character")==ch:returnidxraiseKeyError(f"dictionary.txt 未找到字符:{ch}")defread_graphics_by_index(graphics_path:Path,index:int)->dict:withgraphics_path.open("r",encoding="utf-8")asf:foridx,lineinenumerate(f):ifidx==index:returnjson.loads(line)raiseIndexError(f"graphics.txt 没有第{index}行")defbuild_svg_animated(paths:list[str],width:int=1024,height:int=1024,per_stroke:float=0.35,gap:float=0.05,y_offset:int=140,# ✅ 向上平移的像素(可调:100~200))->str:""" 输出:黑色背景 + 白色笔画(按顺序出现)+ 写字格(外框实线,中线虚线) 并将字整体向上平移 y_offset 像素。 """# 颜色bg_color="black"char_color="white"# 写字格样式outer_opacity=0.35inner_opacity=0.25outer_width=10# 外框线宽inner_width=8# 中线线宽dash="48 36"# 中线虚线样式:线长/间隔(按观感可调)svg_lines=[f'<svg xmlns="http://www.w3.org/2000/svg" width="{width}" height="{height}" viewBox="0 0{width}{height}">',f'<rect width="100%" height="100%" fill="{bg_color}"/>',]# 外框(实线)svg_lines+=[f'<g stroke="white" stroke-opacity="{outer_opacity}" stroke-width="{outer_width}" fill="none" 'f' vector-effect="non-scaling-stroke" shape-rendering="crispEdges" 'f' stroke-linecap="butt" stroke-linejoin="miter">',f' <rect x="{outer_width/2}" y="{outer_width/2}" width="{width-outer_width}" height="{height-outer_width}" />','</g>',]# 中线(虚线:断线效果)svg_lines+=[f'<g stroke="white" stroke-opacity="{inner_opacity}" stroke-width="{inner_width}" fill="none" 'f' vector-effect="non-scaling-stroke" shape-rendering="crispEdges" 'f' stroke-linecap="butt" stroke-linejoin="miter" stroke-dasharray="{dash}">',f' <line x1="{width/2}" y1="0" x2="{width/2}" y2="{height}" />',f' <line x1="0" y1="{height/2}" x2="{width}" y2="{height/2}" />',# 如果你想要“米字格”对角线(也是虚线),取消注释:# f' <line x1="0" y1="0" x2="{width}" y2="{height}" />',# f' <line x1="{width}" y1="0" x2="0" y2="{height}" />','</g>',]# 笔画组(白色填充),翻转 Y 轴,并向上平移# 关键:translate(0, height - y_offset) + scale(1, -1)svg_lines.append(f'<g fill="{char_color}" stroke="none" fill-rule="evenodd" 'f'transform="translate(0,{height-y_offset}) scale(1,-1)">')# 按笔画顺序逐个显现t=0.0fori,dinenumerate(paths,start=1):begin=f"{t:.2f}s"dur=f"{per_stroke:.2f}s"svg_lines.append(f' <path d="{d}">{i}" opacity="0">')svg_lines.append(f' <animate attributeName="opacity" from="0" to="1" begin="{begin}" dur="{dur}" fill="freeze" />')svg_lines.append(" </path>")t+=per_stroke+gap svg_lines.append("</g>")svg_lines.append("</svg>")return"\n".join(svg_lines)defmain():base=Path(__file__).parent dict_path=base/"dictionary.txt"graphics_path=base/"graphics.txt"ch="拓"idx=find_char_line_index(dict_path,ch)g=read_graphics_by_index(graphics_path,idx)strokes=g.get("strokes")ifnotstrokes:raiseValueError("graphics.txt 对应行里没有 strokes 字段或为空")# ✅ y_offset 可根据观感微调:100~200svg=build_svg_animated(strokes,per_stroke=0.35,gap=0.05,y_offset=140)out=base/f"{ch}_animated.svg"out.write_text(svg,encoding="utf-8")print(f"[OK] 已生成:{out}")if__name__=="__main__":main()五、项目价值与影响
Make Me a Hanzi不只是一个数据仓库,它为中文学习与汉字教学工具提供了标准、可扩展的基础资源。它的开放性让其他开发者可以基于此构建更复杂、互动性更强的系统。
经过多年积累,该项目已在多个场景被实际采用,在汉字可视化和学习工具集成方面发挥了显著影响。
六、未来发展与可能性
虽然项目本身已经包含了大量数据,但仍有一些可扩展方向:
- 支持更广泛的 Unicode CJK 范围
- 完善简繁体或日语汉字笔顺差异数据
- 动态生成更多格式的输出(如 GIF、矢量动画)
这些都能够进一步增强汉字学习体验和应用兼容性。
七、总结
Make Me a Hanzi是一个极具价值的开源汉字数据项目,通过结构化和图形化的数据支持,让汉字学习和应用开发变得简单、可扩展。无论你是教育应用开发者、汉字学习者,还是想为自己的项目添加笔顺支持,该项目都值得深入探索。
更多详情请访问它的 GitHub 仓库:
https://github.com/skishore/makemeahanzi GitHub