莱斯学院 · Clavis Academy视觉输入法

视觉输入法 · API 调用说明 / Visual Input · API Guide

中文在前,English follows each section. 公开页面:https://chu.ac.nz/p/ime-api.html(由本文生成)。

1. 它是什么 / What it is

中文 视觉输入法(视觉检字法)不用拼音,也不用背字根:看字由哪些部分组成,笔画 → 构件(含变形)→ 构件的位置 → 候选字,一步步找到字。莱斯学院把它做成了公开接口和可嵌入组件,其他网站、App、教学平台不需要再自己开发。

English The visual input method finds a character by sight, not by pinyin or memorised codes: strokes → parts (variants included) → the part's position → candidate characters. It is available as a public API and an embeddable widget, so other sites, apps and learning platforms do not need to build it again.

三种用法,选一种 / Three ways to use it:

用法 / Way 适合 / Best for 工作量 / Effort
A. iframe 组件 https://chu.ac.nz/embed/ime 网页,想要现成的完整键盘 / web pages that want the ready-made keyboard 几行代码 / a few lines
B. REST 接口 https://chu.ac.nz/v1/ime/… 自己做界面(网页、App、小程序、游戏) / building your own UI 自己画界面 / you draw the UI
C. 离线数据 GET /v1/ime/data + 本文算法 无网络环境、桌面/手机输入法 / offline, native IMEs 自己实现算法(很短) / implement the short algorithm

2. 通用规则 / Common rules

3. 概念 / Concepts

4. 接口 / Endpoints

GET /v1/ime

说明、八个笔画(含键位)、数量。/ Info, the eight strokes with their keys, counts.

{"name":"Clavis visual stroke input (视觉检字法)","version":2,"strokes":[{"key":1,"code":"h","glyph":"一","zh":"横","en":"horizontal"}, …],"counts":{"parts":835,"positions":43,"characters":1649}}

GET /v1/ime/components

笔画 → 构件。/ Strokes → parts.

参数 Param 说明 Description
strokes 已点的笔画(可空:空则返回最常用的构件)/ strokes tapped so far (empty = most common parts)
used 已选过的构件,逗号分隔,不再返回 / parts already chosen, comma-separated, excluded
limit / offset 分页,limit 默认 60,最大 500 / paging, default 60, max 500

规则 Rule:构件的笔画里必须包含所点的笔画;和所点笔画完全一样的构件(match:"exact")排最前,其余按使用频率从高到低(freq,越大越常用)。match 为 exact、prefix(以所点笔画开头)、ordered(顺序包含)、loose(只是包含)。/ The part's strokes must contain the tapped strokes; an exact match comes first, the rest by usage frequency (freq, higher = more common).

GET /v1/ime/components?strokes=s&limit=3
{"strokes":["s"],"total":498,"items":[
 {"glyph":"丨","strokes":"s","freq":2008,"match":"exact"},
 {"glyph":"口","strokes":"s,z,h","freq":70954,"match":"prefix"},
 {"glyph":"亻","strokes":"p,s","freq":70200,"match":"ordered"}]}

GET /v1/ime/positions

构件可能出现的位置。/ Where a part can appear.

参数 Param 说明
part 构件字形,必填 / the part glyph, required
with 已选的组合 构件@位置,…;有它时只统计还能剩下的字 / already chosen pairs part@pos,…; counts only the characters still possible
GET /v1/ime/positions?part=阝
{"part":"阝","items":[{"code":"A02","name":"左","mask":"1100110011001100","count":22},{"code":"A04","name":"右","mask":"0011001100110011","count":4}]}

count 是这个位置下有几个字;最大的就是“最常见的位置”。/ count = characters at that position; the largest is the most common place.

GET /v1/ime/candidates

候选字。/ Candidate characters.

参数 说明
parts 构件@位置,逗号分隔,最多 6 个;多个取交集,必填 / part@pos list (max 6), intersected, required
limit 默认 60,最大 300 / default 60, max 300
GET /v1/ime/candidates?parts=阝@A02&limit=3
{"total":22,"items":[{"glyph":"阶","freq":12535},{"glyph":"队","freq":11438},{"glyph":"际","freq":8249}]}

freq 是字频,大的在前。/ freq is character frequency; higher first.

GET /v1/ime/char/{字}

一个字拆成哪些(构件, 位置)。/ How a character decomposes.

GET /v1/ime/char/明
{"glyph":"明","freq":24518,"parts":[{"part":"月","pos":"A04","posName":"右"},{"part":"日","pos":"A02","posName":"左"}]}

GET /v1/ime/data

整套数据(带 ETag,支持 If-None-Match 返回 304,约 100 KB)。格式 / format:

{"strokes":[[code,glyph,pinyin]],
 "comps":[[glyph,"z,s",freq]],            // 构件:字形、笔画序列、使用频率
 "pos":[[code,name,mask16]],              // 位置
 "rows":[[char,part,posCode,(1=推导)]],    // 字 = 构件 + 位置(一个字有多行)
 "freq":{char:n}}                         // 字频

5. 用法 A:iframe 组件 / Way A: the iframe widget

<textarea id="box"></textarea>
<iframe src="https://chu.ac.nz/embed/ime?lang=zh" style="width:100%;height:420px;border:0" title="视觉输入"></iframe>
<script>
const box = document.getElementById('box');
addEventListener('message', e => {
  if (e.origin !== 'https://chu.ac.nz' || e.data?.source !== 'clavis-ime') return;
  const m = e.data;
  if (m.type === 'insert') { box.setRangeText(m.text, box.selectionStart, box.selectionEnd, 'end'); box.focus(); }
  if (m.type === 'backspace') { /* 删前一个字符 / delete the previous character */ }
  if (m.type === 'enter') { /* 换行或提交 / newline or submit */ }
  if (m.type === 'height') document.querySelector('iframe').style.height = m.height + 'px';
});
</script>

6. 用法 B:REST + 小封装 / Way B: REST and the tiny SDK

import { clavisIme } from 'https://chu.ac.nz/sdk/clavis-ime.mjs';
const ime = clavisIme();
const a = await ime.components('2');                 // 点“竖” / tap vertical
const b = await ime.positions('阝');                  // 阝 的位置 / positions of 阝
const c = await ime.candidates([['阝', 'A02']]);     // 候选字 / candidates
curl 'https://chu.ac.nz/v1/ime/components?strokes=2&limit=5'
curl 'https://chu.ac.nz/v1/ime/candidates?parts=%E9%98%9D@A02'

推荐的界面流程 Recommended UI flow 1. 用户点笔画 → 调 components?strokes=…,列出构件(常用在前)。/ stroke tap → list parts. 2. 点构件 → 调 positions?part=…&with=…。只有一个位置就自动选;最大 count 的位置标“常见”并默认高亮。/ part tap → positions; auto-pick if only one; mark the biggest count as common. 3. 点位置 → 把 构件@位置 加进列表,调 candidates?parts=… 立刻显示候选字。/ position tap → candidates right away. 4. 想缩小范围 → 回到 1,把已选构件放进 used,再加一个构件。/ narrow: repeat with used. 5. 点候选字 → 输入。/ tap a character → insert. 6. 实体键盘:1–8 = 笔画,空格/回车选中,←→ 换选,退格退一步,Esc 清空。/ keyboard shortcuts.

7. 用法 C:离线实现 / Way C: offline

取 /v1/ime/data 缓存到本地,然后:/ Cache /v1/ime/data, then:

components(picked):   候选 = 构件中 笔画 ⊇ picked(多重集包含)
                      排序 = exact(笔画与 picked 完全相同)在前,其余按 freq 降序
positions(part):      统计 rows 中该构件各位置的字数,count 降序
candidates(pairs):    每个 (part,pos) 取 rows 里的字集合,求交集,按 freq[char] 降序

参考实现 / Reference implementation:https://chu.ac.nz/js/imecore.mjs(约 100 行,无依赖,浏览器和 Node 通用)。

8. 版本与变更 / Versioning

接口路径带 /v1/;新增字段不算破坏性变更,请忽略不认识的字段。若有破坏性变更会换成 /v2/ 并保留 /v1/ 一段时间。/ Paths are under /v1/. New fields are not breaking: ignore unknown ones. Breaking changes will ship under /v2/, with /v1/ kept for a while.