我们发现:
为了将来我们的web slides中能够用上CanvasTextEditor, 我们需要重构一下我们的代码.
src/core/CanvasTextEditor.ts
, 为编辑器加上位置属性, 宽高属性, 样式属性:src/demo/App.tsx
, 给编辑器传入位置信息:src/core/CanvasTextEditor.ts
:实现render函数, 渲染一个临时边框:
添加renderBorderCirclor函数, 渲染边框上的8个圆形控制点:
如下图所示:
一张幻灯片(Slide)中可能有多个编辑器(Editor), 一个编辑器中可能有多个段落(Paragraph), 一个段落中可能有多行(SoftLine), 一行中可能有多个字符(Char).
接下来, 我们按照自顶向下的方式, 来一步步实现这个架构:
src/core/CanvasTextEditor.ts
, 添加一个字段 paragraphs:其中, 每个Paragraph要接收这几个参数:
chars: Char[]
为什么Paragraph的构造函数里, 要直接接收Char列表, 而不是SoftLine列表呢? 因为一个SoftLine并不是真正的一行, 而是根据每个Char的宽度和Paragraph的maxWidth, 实时计算出来的. 我们以后将会实现这样的feature: 如果用户调整了Editor的大小, Paragraph的maxWidth随之改变, 所有的SoftLine都会重新计算. 类似下图一样:
src/core/CanvasTextEditorParagraph.ts
如上图, 在构造Paragraph时, 我们需要实现2个逻辑:
calcLayoutForSoftLines
: calcLayout
: 然后, 我们来实现这两个逻辑:
新建src/core/CanvasTextEditorSoftLine.ts
文件, 并在其构造函数中, 计算传入的所有chars的位置:
src/core/CanvasTextEditorChar.ts
文件:color
和fontSize
两个样式:setPosition
方法, 方便在SoftLine中为每个Char设置位置:由于之前src/core/CanvasTextEditorText.ts
中的逻辑现在已经分散到了Paragraph, SoftLine, Char中, 所以现在可以删除这个文件.
截止到目前为止, 出现了一个小问题: 一行内不同大小的文字, 他们的纵向对齐方式, 是以顶部为基线的.
为了看得更清楚, 我们给每个字符加上辅助边框和背景色, 修改src/core/CanvasTextEditorChar.ts
:
修改src/core/CanvasTextEditor.ts
, 再加上几个汉字:
这样, 可以更清晰地看出, 不同大小的文字是顶部对齐的:
为什么会出现行内文字纵向顶部对齐呢? 因为我们之前为了方便, 将textBaseline
设置为了top
:
这样设置之后, 包围盒顶部坐标 和 fillText(text, x, y)
中的y坐标就相等了. 我们之前把它们统一记作top
.
现在, 我们不得不放弃之前的偷懒方式, 将两者分别记录:
fillText(text, x, y)
中的y
记作top
boundingBoxTop
修改src/core/CanvasTextEditorChar.ts
:
看一下效果:
这次行内文字纵向对齐的问题解决了, 可是新的问题来了: 为什么所有的文字整体上移了?
因为我们已经把textBaseLine
恢复成了默认值alphabetic
. 绘制文字的基线下移了, 且文字的坐标(left, top)没变, 所以相当于文字上移了.
为了解决这个问题, 我暂时想到了一种方法:
offsetY
offsetY
, 取决于行内所有字符fontBoundingBoxAscent
的最大值接下来我们来实现, 修改src/core/CanvasTextEditorSoftLine.ts
:
效果:
文字上移的问题解决了, 棒!
(未完待续)