canvas-editor
canvas-editor copied to clipboard
编辑器支持rtl渲染
实现仓库:https://github.com/HerbertHe/canvas-editor/tree/feature/rtl
目前还在对此部分进行实现,已经完成进度如下:
- [x] 支持 mock 渲染 rtl
- [x] 支持 mock rtl 和 ltr 的切换
- [x] 支持
setDirectiongetDirectioncommand - [x] 修正了 rtl 下的 demo 布局
- [x] 修正了 rtl 下的 range
- [x] 修正了 rtl 下,canvas 文本与非文本绘制的差异,重新计算差异坐标
- [x] 修正了 rtl 下,光标的碰撞检测
- [x] 修正了非文本的绘制
- [x] 修正了普通文本的绘制
- [x] 修正了 separator 不正确的坐标问题
- [x] ~~underline 绘制坐标的偏移错误~~ #469
- [x] ~~strikeout 绘制坐标的偏移错误~~ #469
- [x] table tool rtl 下进行反方向绘制
- [x] 在 rtl 下,普通文本和带特殊格式的文本存在定位混排错误的问题 #468
- [x] ~~超链接渲染缺陷,没有遵守 rtl 的文字排版~~ 将 hyperlink 的绘制交给 textParticle 完成
已知需要修复的问题:
- [ ] 计算 rtl 下,居中和左对齐坐标
- [ ] highlight 块错误的绘制坐标
- [ ] table 的绘制问题适配
- [ ] 在 rtl 下,富文本 command 操作存在差异
- [ ] 在 rtl 下,富文本 keydown 存在差异
- [ ] 修复文本重排导致的 element 选择错误问题
- [ ] 修复 checkbox 文本绘制的问题 #477
- [ ] 修复上下角标的绘制问题
还有就是数字列表的渲染,实际上来看似乎列表渲染和文字渲染是分开割裂的
非常好!期待pr,之前渲染没有考虑rtl,默认从左到右绘制会存在坐标问题
@Hufe921 还在计算坐标,现在已知的情况是文本绘制不存在问题,也已经完成了rtl模式下的鼠标碰撞检测计算镜像坐标。但是图片这些仍然存在问题,感觉是这部分渲染坐标导致的。
- [x] 完成 mousedown event 下碰撞检测计算问题
已知问题是 ctx.fillRect 方法不支持 ctx.direction='rtl',表现与文本绘制完全不一致
@Hufe921 #457 我仍然觉得这是一个单独的可以改善的地方,下面是我对此的一些看法;
我完整阅读了您的理由,觉得可能您误解了我的意思,所以这部分即使是单独绘制的,仍然需要针对 RTL 字符进行改善。先回复您的回答原因,然后我再举例说明实际的问题,这里面涉及到阿拉伯字母连字的问题。
我认为 ctx.direction 的实现是一个最好的方案,原因如下:
- 这个属性并不是实验性的 Browser compatibility
ctx.direction解决的是 LTR 和 RTL 混排的问题,而不是 RTL 布局的问题,即使完全不依赖浏览器的渲染逻辑,对于文本来说,自行绘制只是对这个属性的重新实现。因为在适配 RTL 过程中,其实只有文本才是交给浏览器处理的,其他的并不受此属性的影响。
针对原因 2,我列举一个混排的例子:
在LTR中,你好 سالەم,
RTL中,应该渲染为 سالەم 你好,而不是 سالەم 好你,非 RTL 标点符号(比如:空格)混排渲染取决于后一个字符的类型,而不是轴对称。在 canvas-editor 的 RTL 针对富文本绘制的逻辑中,ctx.direction 是正确的,并且处理了光标的异常问题,我重新实现了 rtl 情况下的光标碰撞检测定位。因此,我才觉得这个特性是最好的文本处理方案。
- 针对您所说的开发瓶颈的问题,RTL 实际上是没法通过统一计算进行解决的,上面我已经列举了混排的例子。针对某个组件或者文字需要 LTR,在我分析源码之后,认为是不存在瓶颈的。绘制需要传递 ctx 引用,渲染函数内进行强制
ctx.direction='ltr'就完全规避了这个问题。
但对文本绘制这一块,逐字符绘制,我必须要举一个例子,这是导致 Date 异常的根本性原因。如果仍然要以逐字符绘制的话,这是最优的改进方案。
上面说到的 سالەم,您所看到的,其实已经是浏览器绘制连字之后的。实际上,如果是单字符渲染,得到的结果是 س ا ل ە م (用空格作为截断),这是缺陷所在,不符合阿拉伯文字的书写渲染。同样,بولادى 渲染也不是 ب و ل ا د ى。
上面的两个例子,为哈萨克语的阿拉伯-波斯字母形式。
所以,我仍然认为需要改进的方向是,重新实现 date.render 方法,应该采用对富文本同样处理的方式,对这部分字符进行处理,阿拉伯字母语言也有年月日。
根据 canvas-editor 对普通文本的渲染表现来看,其实是已经进行了合并处理的,单个渲染一定会出现我上面所述的问题,连字的问题无法进行自行实现计算坐标解决。
所有 RTL 渲染的逻辑其实都是先按照 RTL 进行处理,遇到 LTR 字符全部按 LTR 处理,但是总体上保持 RTL 的方向和顺序。一旦不以 LTR 为第一渲染计算根本,就带来了 left 和 right 概念错误的问题,因为不存在左右,而是前后。RTL 在排版上,默认为右对齐,左对齐才是 canvas-editor 进行填充偏移绘制的方法,其实是:前对齐/后对齐
@Hufe921 对此问题进行了修复
else if (element.type === ElementType.DATE) {
const before = curRow.elementList[j - 1]
const next = curRow.elementList[j + 1]
// 设置释放之前的
if (!before || (!!before && before.type !== 'date')) {
this._drawRichText(ctx)
}
this.textParticle.record(ctx, element, x, y + offsetY)
if (!next) {
// 手动触发渲染
this.textParticle.complete()
}
}
借用了 textParticle 的绘制能力
https://github.com/Hufe921/canvas-editor/issues/451#issuecomment-1991805739 提到的连写问题,在两端对齐中就表现出来了
右对齐就不存在这个问题
两端对齐断开,其实也符合情况,右对齐就不能出现字符连写断开的情况了
内容来源于中国哈萨克语广播网 http://www.kazakcnr.com/zdgz2019/toutiao/202403/t20240311_1515669.html
存在超链接渲染的缺陷,具体表现如 Date
#468 @Hufe921
重构之后文本 rtl 渲染结果相对正常,只需要处理 underline、strikeout 等重绘坐标即可