前言
之前计划自己业余时间做一个类似 Figma 或 Miro 的白板编辑器:Blitz:可以实时聊天的多人协同白板。在完成框架搭建并开始实现具体子功能时,我发现独自完成这个项目的工作量非常大,一蹴而就并不现实,例如文字和路径这两个功能自身复杂度就很高。因此,目前我决定先从实现各个子元素入手,逐步将每个功能集成到编辑器中,这样不仅可以使开发节奏更可控,也更容易坚持完成项目。
更强大的文字组件
白板编辑器中的文字元素通常具有丰富的功能,如字间距、行间距、描边、阴影和模糊效果等。实现这些效果本身就有不小的工作量和挑战,而要通过 input、textarea 这些组件在输入时实现与目标渲染效果完全一致,更是难上加难,而且非常不可控。因此,我最近基于 Skia 自己开发了一个集排版、渲染和输入于一体的文字组件:TextMagic。
目前,这个组件正在快速接近完整功能。本文将简要介绍该组件的设计思路,以及开发一个全面的文字组件所需的各种能力,但是不会涉及很细节的比如光标如何兼容换行符、在富文本下如何拆分/合并文本内容与样式、如何基于 Skia 实现具体能力之类的逻辑,因为这部分逻辑很繁琐且无聊,而且不同的设计可能有不同的实现,感兴趣的可以按需直接查看源码会了解得更充分些。
原型演示
体验地址:TextMagic - A Next Generation of Text Input ,初始化的时候会一次性拉取 10MB 左右的资源,个人 ECS 网速有限,可能要等待 10-20 秒的时间。
组件设计
目前在文字渲染也就是 @text-magic/renderer 中,列表文字的实现是通过插入另外一个 canvas 来实现的,是一种比较取巧的方式,后续会有比较大的调整可能,即将列表文字也纳入到完整的渲染组件中,并且对于 input 输入组件可感,所以这里组件设计上就不体现了。
数据结构
在数据结构的设计上目前尽可能参考 CSS 的标准,在其基础上按需删减或增加 。TMInput、TMRenderer 的接口设计相对简单,主要要对接的就是排版(measure) 以及 渲染(render) 两个接口,其他的都是常见的注册字体等 API ,包括光标、选取如何展示,文字以及富文本样式如何插入这些都是内聚在组件内部的,只是使用组件的话并不需要过于关注。所以这里面最关键的还是 TMTextData 以及 TMTextMetrics ,这两个决定了组件间通信应该传递哪些数据以及限定规则。
这里只介绍核心 API 以及数据字段,其他更细节的可以看 text-data.d.ts、text-input.d.ts 、text-renderer.d.ts 以及接口注释(在补了在补了~)和相应的代码逻辑。
性能测试
目前还没有进行系统性的测试(单测&自动化测试也在补充中),不过在自己和几个同事体验的主观感受反馈,跟原生的 input、textarea 等组件并没有明显性能上的差异,预计会在一个月内把这块补充上。
功能清单
文字排版
- 字体
- 字号
- 文字颜色
- 行高
- 字间距
- 行间距
- 首行缩进
- 水平对齐
- 左对齐
- 居中对齐
- 右对齐
- 分散对齐
- 垂直对齐
- 列表文字
- 无序列表-实心圆
- 无序列表-空心圆
- 有序列表-阿拉伯数字
- Emoji
- 混合排版
- 换行
- 竖排
- 书写方向
- 从左往右
- 从右往左
- 从上到下
- 从下到上
文字效果
- 加粗
- 倾斜
- 装饰线
- 下划线-实线
- 下划线-波浪线
- 删除线-实线
- 删除线-波浪线
- 描边
- 阴影
- 模糊
- 背景
- 高亮
- 背景填充颜色
- 圆圈框选
- 打叉
- 文本框背景
快捷键
- Ctrl/CMD + A 全选
- Ctrl/CMD + C 复制
- Ctrl/CMD + X 剪切
- Ctrl/CMD + V 粘贴
- Ctrl/CMD + Z 撤销
- Ctrl/CMD + Y 重做
- Ctrl/CMD + 左箭头 移动到行首
- Ctrl/CMD + 右箭头 移动到行尾
- Shift + 左箭头 选中前一个字符
- Shift + 右箭头 选中下一个字符
- Shift + 上箭头 向上选中一行
- Shift + 下箭头 向下选中一行
- 上箭头 向上移动
- 下箭头 向下移动
- 左箭头 向左移动
- 右箭头 向右移动
- Home 移动到文本框的开头
- End 移动到文本框的结尾
用户交互
- 文本框尺寸调整
- 宽高自适应
- 固定宽度
- 固定高度
- 显示溢出文本框内容
下一步
近期我将对 TextMagic 进行以下完善:
- 规整代码结构,提升可读性;
- 支持包引用与组件创建;
- 实现用户交互功能;
- 进行系统性的测试覆盖。
其他可能的改进将根据需求逐步进行。如果一切顺利,我将开始着手路径等子元素的开发。希望这个组件能够帮助到需要实现一致文字渲染与输入效果,并具备丰富文字效果需求的用户。如有任何问题或建议,欢迎交流~