解决 TinyMCE 在移动端软键盘弹起时光标被遮挡的问题

2026-05-26 145 浏览 0 评论

在移动端页面中使用 TinyMCE 作为富文本编辑器时,一个比较常见的问题是: 当软键盘弹起后,当前编辑位置会被键盘遮挡 。用户继续输入时,光标所在的文本区域并不在可视范围内,必须手动滚动页面才能看到当前输入位置,体验较差。

这个问题在移动浏览器、WebView 以及 Hybrid 应用中都可能出现,其根本原因并不在于编辑器本身,而是 软键盘改变了可视区域高度,但页面滚动位置没有同步调整

本文记录一个实际项目中的解决方案,通过监听编辑器状态并主动调整页面滚动,使光标始终保持在可见区域。


问题产生的原因

移动端软键盘弹起时,浏览器会改变视口高度(viewport)。但页面本身的滚动位置并不会自动调整,而富文本编辑器内部通常是一个独立的内容区域。

当用户在页面下方输入内容时,可能会出现以下情况:

  1. 光标位置在页面下半部分
  2. 软键盘弹出,占据了屏幕底部空间
  3. 当前编辑节点落入键盘覆盖区域
  4. 页面没有自动滚动

结果就是用户无法看到自己正在输入的内容。

因此需要在编辑器状态变化时 检测当前光标节点的位置,并根据可视区域动态滚动页面


解决思路

解决这个问题的核心思路是:

  1. 获取当前光标所在的节点
  2. 计算该节点在页面中的位置
  3. 判断该位置是否落入键盘遮挡区域
  4. 如果被遮挡,则滚动页面

关键步骤包括:

  • 监听编辑器 focus 事件
  • 监听内容节点变化 NodeChange
  • 获取节点 getBoundingClientRect()
  • 根据可视区域高度进行滚动调整

实现代码

初始化编辑器时,在 setup 生命周期中绑定事件:

tinymce.init({
  selector: '#editor',
  setup(editor) {
    const scrollIntoView = () => {
      const node = editor.selection.getNode()
      if (!node) return

      const rect = node.getBoundingClientRect()
      const keyboardOffset = 300

      if (rect.bottom > window.innerHeight - keyboardOffset) {
        window.scrollBy({
          top: rect.bottom - window.innerHeight + keyboardOffset,
          behavior: 'smooth'
        })
      }
    }

    editor.on('focus', scrollIntoView)
    editor.on('NodeChange', scrollIntoView)
  }
})

代码逻辑解析

1 获取当前光标节点

const node = editor.selection.getNode()

selection.getNode() 会返回当前光标所在的 DOM 节点。例如:

  • 段落 <p>
  • 列表 <li>
  • 标题 <h2>

该节点代表当前正在编辑的内容区域。


2 获取节点的屏幕位置

const rect = node.getBoundingClientRect()

getBoundingClientRect() 返回元素相对于 当前视口 的位置,例如:

top
bottom
left
right
height
width

其中 bottom 表示节点底部距离视口顶部的距离。


3 计算软键盘遮挡区域

const keyboardOffset = 300

移动端软键盘通常会占据 250px ~ 350px 的屏幕空间,因此可以设置一个安全偏移值。

接下来判断节点是否落入键盘区域:

rect.bottom > window.innerHeight - keyboardOffset

如果成立,说明节点已经接近或进入键盘遮挡区域。


4 自动滚动页面

当节点被遮挡时,通过 window.scrollBy() 调整页面:

window.scrollBy({
  top: rect.bottom - window.innerHeight + keyboardOffset,
  behavior: 'smooth'
})

滚动距离的计算逻辑:

节点底部位置
- 当前可视高度
+ 键盘安全距离

这样可以将当前编辑节点滚动到键盘上方。

smooth 动画可以避免页面突然跳动。


5 监听编辑器状态变化

代码绑定了两个事件:

editor.on('focus', scrollIntoView)
editor.on('NodeChange', scrollIntoView)

含义分别是:

  • focus :编辑器获得焦点时触发
  • NodeChange :光标移动到不同节点时触发

这样在以下场景都会自动调整页面:

  • 用户点击编辑器开始输入
  • 用户换行
  • 光标移动到新的段落
  • 编辑不同的文本块

运行效果

当用户在页面下方编辑内容时:

  1. 软键盘弹出
  2. 编辑器检测当前光标节点
  3. 判断是否被遮挡
  4. 页面自动滚动
  5. 当前输入内容始终保持在键盘上方

整个过程对用户是无感的,编辑体验会明显提升。


总结

在移动端使用 TinyMCE 进行富文本编辑时,软键盘遮挡输入位置是一个常见问题。通过监听编辑器状态变化并结合节点位置计算,可以在光标接近键盘区域时自动调整页面滚动,从而保证当前编辑内容始终处于可见范围内。

该方法实现简单、侵入性低,并且适用于大多数移动浏览器和 WebView 环境。


发布评论

发布评论前请先 登录
取消
0 评论
点赞
收藏

评论列表 0

暂无评论