- Canvas Demo 改名「绿叶」移到 skins/green_leaf 随安装包分发,设置页列在内置皮肤之后 - border_image 新增可选 light_source,浅色主题换用另一张面板图;绿叶补上浅色面板与配色 - Mica / Acrylic 样例移到 skins/mica、skins/acrylic 随包分发,名字去掉 Demo - 外部皮肤没写 toolbar handle 时取同主题 accent;Fluent 拖动条改为强调色 #6B69D6, 首道-蓝、搜狗经典·石墨的拖动条改成各自的 accent,清单测试检查两者一致 - 「重启输入法进程」「设置窗口后台驻留」从外观页移到关于页
9.7 KiB
Metasequoia IME skin example
水杉输入法(Metasequoia IME)外部皮肤的官方样例。一个皮肤就是一个文件夹,外观全部写在一份 skin.toml 里:候选框的装饰图、背景图、圆角和配色,以及悬浮工具栏的配色。不需要写 CSS,也不会加载任何脚本。
更多现成皮肤见仓库根目录的 skins/。
- 字段说明:schema/README.md
- 本地预览:preview.html
快速开始
- 复制
skins/niya-demo/,把文件夹名和skin.toml里的id改成同一个新名字。 - 替换
assets/里的图片:character.png:卡片上方的人物装饰,建议透明 PNG。background.png:卡片背景纹理。深浅两套主题共用这张图,建议大部分透明。
- 修改
skin.toml中的名称、作者、尺寸和配色。 - 用浏览器打开
preview.html,大致确认横向、纵向两种候选框的效果。 - 把皮肤文件夹复制到
%LOCALAPPDATA%\metasequoiaime\skins\,打开设置里的“皮肤”页面(会自动扫描),或者点“刷新皮肤”。
也可以直接运行安装脚本装上样例皮肤:
./install.ps1 # 复制到 %LOCALAPPDATA%\metasequoiaime\skins\niya-demo\ 并启用
./install.ps1 -NoActivate # 只复制,不改 config.toml
启用即把 config.toml 中的 appearance.candidate_skin 设为 niya-demo。装好后重启水杉输入法服务即可生效。
设置页会读取 skins\ 下每个一级子目录中的 skin.toml。目录名与 id 不一致或字段不合法时,该皮肤不会出现在可选列表里,原因会显示在页面底部的诊断信息中。
目录结构
examples/skin-examples/
├─ skins/
│ ├─ niya-demo/ # 一个皮肤一个文件夹,文件夹名 = id
│ │ ├─ skin.toml # 元信息、候选框、工具栏、授权
│ │ └─ assets/
│ │ ├─ character.png # 卡片上方的装饰图
│ │ └─ background.png # 卡片背景图
│ └─ sakura-night/ # v2 实机演示「夜樱」:面板后的月亮、APNG 花瓣、GIF 星星
│ ├─ skin.toml
│ └─ assets/
│ ├─ panel.png # 九宫格面板(2 倍图,四角小樱花不随拉伸变形)
│ ├─ moon.png # 面板下层挂件
│ ├─ petals.apng # 面板上层的循环 APNG 挂件
│ └─ stars.gif # 面板上层的循环 GIF 挂件
├─ schema/ # manifest 字段说明
├─ tools/ # 生成样例图片的脚本(需要 Pillow)
├─ tests/ # CI 用的 manifest 与安装脚本测试
├─ preview.html # 本地预览
└─ install.ps1 # 样例安装脚本
只有 skins/<id>/ 会被安装,preview.html、schema/、tools/、tests/ 和安装脚本都只是制作工具。
样例皮肤能演示什么
niya-demo 的 skin.toml 每一段都带注释,下面是最常改的几处:
[candidate_window]
min_width_dip = 176
corner_radius_dip = 12 # 0–32,不写则沿用 base
item_corner_radius_dip = 6 # 高亮圆角,0–16
shadow = "soft" # none | soft | strong
[candidate_window.decoration]
image = "assets/character.png"
top_inset_dip = 88 # 装饰框高度
width_dip = 102 # 装饰框宽度
align = "right" # left | center | right
[candidate_window.background]
image = "assets/background.png"
fit = "cover" # cover | contain | stretch
opacity = 0.3 # 0–1
[candidate.dark]
accent = "#e08aa8" # 光标与选中胶囊条
selected = "rgba(224, 138, 168, 0.28)"
hover = "rgba(224, 138, 168, 0.16)"
preedit_text = "#f0b8cb" # 细分配色都可省略,见 schema/README.md
preedit_divider = "rgba(224, 138, 168, 0.30)"
[candidate.dark.menu] # 右键菜单
background = "#221a1e"
hover = "rgba(224, 138, 168, 0.20)"
[toolbar]
corner_radius_dip = 8
[toolbar.dark]
background = "#221a1e"
handle = "#e08aa8"
icon = "#f6e4eb"
几个要点:
- 装饰图放在一个
width_dip × top_inset_dip的框里等比缩放,框贴在卡片正上方,不会与卡片重叠。框的比例和原图一致时就不会留白,比如样例原图是 408×353,所以用了 102×88。 - 卡片实际最小宽度取
min_width_dip和装饰图width_dip中较大的那个。 - 背景图画在底色之上、文字之下,并按圆角裁剪。
- 细分配色(普通候选文字、预编辑文字与光标、选中行的文字 / 序号 / 翻译 / 竖条、预编辑底色与分隔线)不写时都回落到
text或accent,完整的回落规则见 schema/README.md。设置页里的「候选文字颜色」仍优先于皮肤的文字色。 - 所有颜色键都可以写十六进制
#rgb/#rgba/#rrggbb/#rrggbbaa,也可以写rgb()/rgba()或transparent。十六进制必须带#,不透明度在末尾(#RRGGBBAA),详见 schema/README.md。 font_family排在用户设置的字体前面,缺字时回落到用户字体;字号始终由用户设置决定。page_arrows = true可以打开候选框里的翻页箭头;不写时沿用base内置皮肤的设置(出厂为关闭)。fit_content = true让卡片严格按候选文字的宽度收紧,不再垫出厂最小宽度;min_width_dip和装饰图宽度仍然生效。不写时沿用base内置皮肤的设置(出厂为关闭)。[toolbar]下的所有键都可以省略,没写的沿用base皮肤;只有拖动条handle例外,没写时跟同一主题的accent。[supports].themes里声明的每套主题都要有对应的[candidate.<theme>];写了[toolbar]的话,也要有对应的[toolbar.<theme>]。
完整字段见 schema/README.md。
全贴图皮肤(schema_version 2)
sakura-night 和随安装包分发的 绿叶(原 canvas-demo)都是 v2 皮肤:schema_version = 2、base = "canvas",候选框的外观全部来自贴图。下面的片段取自绿叶。
schema_version = 2
base = "canvas" # v2 必须以 canvas 为 base
[candidate_window.border_image]
source = "assets/panel.png" # 64×64 的 2 倍图
light_source = "assets/panel-light.png" # 可选:浅色主题换这张,几何与 source 相同
slice_dip = [20] # 切片线,按源图像素
width_dip = [10] # 边框绘制宽度,按 DIP:2 倍图写切片的一半,200% 缩放下逐像素清晰
[[candidate_window.decorations]]
image = "assets/sparkle.apng" # APNG / GIF 动图会播放
anchor = "top-right"
offset_x_dip = 10
offset_y_dip = -12
width_dip = 24
height_dip = 24
z_index = 2 # z_index < 1 画在面板之下,其余画在面板之上
canvas本身透明、无描边、无圆角、无阴影,不能单独选用;面板图、挂件和配色都由皮肤给出。- 面板四角画死的花纹要落在切片之内,否则会被拉伸。中心块可以用
fill = false留空。 - 文字离面板外缘的距离用
content_insets_dip,挂件伸出卡片时用outer_insets_dip给窗口留出空白。 - 动图在系统关闭「动画效果」时只显示第一帧。动图解码后合计不超过 64 MB、最多 1024 帧,超出时只显示第一帧。
- 绿叶和夜樱的图都是程序生成的几何图形,以 MIT 授权,可以直接改用;绿叶的浅色面板由
tools/gen_green_leaf_panel.py生成。
sakura-night(夜樱)是一个更完整的实机演示,把 v2 的能力都用上了:
- 紫夜玻璃九宫格面板,四角的小樱花落在 24 像素切片内,候选框怎么伸缩都不变形。
- 月亮挂在右上角、
z_index = -1画在面板之后,只露出伸出面板的那一截。 - 右侧飘落的花瓣是 24 帧 × 70 ms 的循环 APNG,左下闪烁的星星是 8 帧 × 150 ms 的循环 GIF。
- 用
content_insets_dip让文字避开边框和四角花纹,用outer_insets_dip给伸出去的挂件留出窗口空间,用line_gap_dip拉开预编辑行与候选。 - 左上角刻意不放挂件:预编辑文字从那里开始,挂件压上去会挡字。
它的图片都由 tools/gen_sakura_night.py 生成(需要 Pillow),重新运行会得到同样的文件:
python tools/gen_sakura_night.py skins/sakura-night
制作约束
- 只用
skin.toml和本地图片,不支持自定义 JavaScript,也不再读取cand.css或工具栏 CSS。 - 图片路径相对于皮肤目录,不能指向目录之外。
id只能包含小写字母、数字、点、下划线和连字符,最长 64 个字符。- 单张图片建议不超过 500 KB(CI 会检查 PNG、APNG、GIF 和 WebP)。
测试
python -m unittest discover -s tests -v # 检查 manifest 与引用的图片
./tests/install.ps1 # 在临时目录里测试安装、启用和重复安装
授权提示
本目录采用 MIT 授权(见 LICENSE),不随仓库其余部分的 GPL-3.0。这个目录就是拿来复制的:把它整个拷走,或者把 skins/niya-demo/ 整个拷走改成自己的皮肤,都不需要额外授权。之所以用 MIT 而不是产品代码的 GPL-3.0,就是为了让你做出来的皮肤可以按自己的意愿授权。
皮肤代码和图片资源可以用不同的许可,发布前请在 skin.toml 的 [license] 里分别写明 code 和 assets。样例中的 assets 标为 UNVERIFIED-DEMO-ONLY,意思是这些图片只用于演示、来源未经核实,请不要直接拿去发布,换成你有权使用的图片。