近期要重构矢量文本的功能,于是尽可能多的收集了这一类的功能实现,最后开始看fabricjs的文本书写的实现。于是阅读了一些源码,这里稍稍记录一下,一次阅读肯定吃不透它的所有实现。
当我们在fabricjs的画布上创建一个文本元素时,大概会这样写
const text = new fabric.IText("双击输入文本", {
left: x,
top: y,
fontSize: 20,
fill: "black",
editable: true,
});
// 添加到画布
this.canvas.add(text);
关于 IText类的详细文档 https://fabricjs.com/api/classes/itext/#acoords 支持的属性非常多
查看源码可以得知在new时,主要执行了这两段代码
initBehavior 这个方法是在ITextClickBehavior 这个抽象类里实现的
另外是 fabricjs支持的 书写文本的交互
* #### Supported key combinations
* ```
* 1: Move cursor: left, right, up, down
* 2: Select character: shift + left, shift + right
* 3: Select text vertically: shift + up, shift + down
* 4: Move cursor by word: alt + left, alt + right
* 5: Select words: shift + alt + left, shift + alt + right
* 6: Move cursor to line start/end: cmd + left, cmd + right or home, end
* 7: Select till start/end of line: cmd + shift + left, cmd + shift + right or shift + home, shift + end
* 8: Jump to start/end of text: cmd + up, cmd + down
* 9: Select till start/end of text: cmd + shift + up, cmd + shift + down or shift + pgUp, shift + pgDown
* 10: Delete character: backspace
* 11: Delete word: alt + backspace
* 12: Delete line: cmd + backspace
* 13: Forward delete: delete
* 14: Copy text: ctrl/cmd + c
* 15: Paste text: ctrl/cmd + v
* 16: Cut text: ctrl/cmd + x
* 17: Select entire text: ctrl/cmd + a
* 18: Quit editing tab or esc
* ```
*
* #### Supported mouse/touch combination
* ```
* 19: Position cursor: click/touch
* 20: Create selection: click/touch & drag
* 21: Create selection: click & shift + click
* 22: Select word: double click
* 23: Select line: triple click
* ```
这23个没有包含换行,特殊字符等处理。可以说非常切合地mock里在文本域中的交互。
在ITextKeyBehavior.ts 这个文件里有写到是使用的 一个隐藏的textarea来实现的 输入效果,包括选择,光标的上下左右移动,复制粘贴
我看的几个方案都是 使用隐藏的textarea来mock,书写动作。
当点击画布时,真实的光标聚焦在隐藏的textarea的中,并在画布上画一个隐藏的光标,并设置动画。 同时监听textarea的这些事件 blur, keydown,keyup ,input ,copy ,cut ,paste ,compositionstart ,compositionupdate ,compositionend ,在这些事件的处理函数中,都需要将内容的修改,或者状态,同步到画布的文本元素上。
在移动画布上的光标时,或者选择内容时,我们必须对字体的宽度和位置有一个清晰的建模。 而这个建模 就是使用 canvas.measureText() 这个方法。 https://developer.mozilla.org/zh-CN/docs/Web…/API/CanvasRenderingContext2D/measureText
在 Text.ts这个文件里我们可以找到相关的代码,
像 this.__charBounds, this._textLines ,每一行的宽度,每个字体的宽度,都是基于这个measureText来计算的。
每一字符都有一个索引,即使换行也不间断。