fix(editor): 切换视图时按滚动比例同步位置

修复切回富文本时编辑器滚动到底部的问题:移除 commands.focus()
(会强制滚动到光标位置),改用滚动比例跨模式同步,富文本与源码
视图按相同比例定位,保持视觉位置一致。
This commit is contained in:
xfy 2026-06-16 15:53:28 +08:00
parent 480aa92bb4
commit 914f168551

View File

@ -163,6 +163,8 @@ class TiptapEditorInstance {
this.sourceTextarea.value = this.editor.getMarkdown()
proseMirrorDom.style.display = 'none'
this.sourceTextarea.hidden = false
// 按滚动比例同步到源码视图,保持视觉位置一致
this.syncScrollRatio(proseMirrorDom, this.sourceTextarea)
this.sourceTextarea.focus()
this.toggleButton.textContent = '✎'
this.toggleButton.title = '切换富文本'
@ -170,16 +172,48 @@ class TiptapEditorInstance {
} else {
// 源码 → 富文本:把 textarea 内容回填到编辑器
const md = this.sourceTextarea.value
// 先记录源码视图的滚动比例setContent 会重建文档,必须在替换前拿到比例)
const sourceRatio = this.getScrollRatio(this.sourceTextarea)
this.setMarkdown(md)
this.sourceTextarea.hidden = true
proseMirrorDom.style.display = ''
// 等待 DOM 布局更新后,按比例同步富文本视图滚动位置
requestAnimationFrame(() => {
this.applyScrollRatio(proseMirrorDom, sourceRatio)
})
this.toggleButton.textContent = '</>'
this.toggleButton.title = '切换 Markdown 源码'
this.isSourceMode = false
this.editor.commands.focus()
// 注意:不调用 editor.commands.focus(),它会强制滚动到光标位置(默认文档末尾),破坏比例同步
}
}
/**
* 0~1
* = scrollTop /
*/
private getScrollRatio(el: HTMLElement): number {
const max = el.scrollHeight - el.clientHeight
if (max <= 0) return 0
return el.scrollTop / max
}
/**
*
*/
private applyScrollRatio(el: HTMLElement, ratio: number): void {
const max = el.scrollHeight - el.clientHeight
if (max <= 0) return
el.scrollTop = max * ratio
}
/**
* 便
*/
private syncScrollRatio(from: HTMLElement, to: HTMLElement): void {
this.applyScrollRatio(to, this.getScrollRatio(from))
}
setMarkdown(content: string): void {
this.editor?.commands.setContent(content, { emitUpdate: false, contentType: 'markdown' })
}