TextMagic:实现编辑特效更丰富的文字组件

300 阅读5分钟

前言

之前计划自己业余时间做一个类似 Figma 或 Miro 的白板编辑器:Blitz:可以实时聊天的多人协同白板。在完成框架搭建并开始实现具体子功能时,我发现独自完成这个项目的工作量非常大,一蹴而就并不现实,例如文字和路径这两个功能自身复杂度就很高。因此,目前我决定先从实现各个子元素入手,逐步将每个功能集成到编辑器中,这样不仅可以使开发节奏更可控,也更容易坚持完成项目。

更强大的文字组件

白板编辑器中的文字元素通常具有丰富的功能,如字间距、行间距、描边、阴影和模糊效果等。实现这些效果本身就有不小的工作量和挑战,而要通过 input、textarea 这些组件在输入时实现与目标渲染效果完全一致,更是难上加难,而且非常不可控。因此,我最近基于 Skia 自己开发了一个集排版、渲染和输入于一体的文字组件:TextMagic

目前,这个组件正在快速接近完整功能。本文将简要介绍该组件的设计思路,以及开发一个全面的文字组件所需的各种能力,但是不会涉及很细节的比如光标如何兼容换行符、在富文本下如何拆分/合并文本内容与样式、如何基于 Skia 实现具体能力之类的逻辑,因为这部分逻辑很繁琐且无聊,而且不同的设计可能有不同的实现,感兴趣的可以按需直接查看源码会了解得更充分些。

原型演示

体验地址:TextMagic - A Next Generation of Text Input ,初始化的时候会一次性拉取 10MB 左右的资源,个人 ECS 网速有限,可能要等待 10-20 秒的时间。

text-magic.gif

组件设计

text-magic-framework

目前在文字渲染也就是 @text-magic/renderer 中,列表文字的实现是通过插入另外一个 canvas 来实现的,是一种比较取巧的方式,后续会有比较大的调整可能,即将列表文字也纳入到完整的渲染组件中,并且对于 input 输入组件可感,所以这里组件设计上就不体现了。

数据结构

在数据结构的设计上目前尽可能参考 CSS 的标准,在其基础上按需删减或增加 。TMInputTMRenderer 的接口设计相对简单,主要要对接的就是排版(measure) 以及 渲染(render) 两个接口,其他的都是常见的注册字体等 API ,包括光标、选取如何展示,文字以及富文本样式如何插入这些都是内聚在组件内部的,只是使用组件的话并不需要过于关注。所以这里面最关键的还是 TMTextData 以及 TMTextMetrics ,这两个决定了组件间通信应该传递哪些数据以及限定规则。

这里只介绍核心 API 以及数据字段,其他更细节的可以看 text-data.d.tstext-input.d.tstext-renderer.d.ts 以及接口注释(在补了在补了~)和相应的代码逻辑。

text-magic-uml.jpg

性能测试

目前还没有进行系统性的测试(单测&自动化测试也在补充中),不过在自己和几个同事体验的主观感受反馈,跟原生的 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 进行以下完善:

  • 规整代码结构,提升可读性;
  • 支持包引用与组件创建;
  • 实现用户交互功能;
  • 进行系统性的测试覆盖。

其他可能的改进将根据需求逐步进行。如果一切顺利,我将开始着手路径等子元素的开发。希望这个组件能够帮助到需要实现一致文字渲染与输入效果,并具备丰富文字效果需求的用户。如有任何问题或建议,欢迎交流~