canvas本身不支持原生文本输入,需结合dom输入框实现光标动画效果:由input/textarea处理实际输入逻辑,canvas仅作为视觉代理,通过事件监听、坐标映射与实时渲染同步光标位置、闪烁及样式。

Canvas 本身不支持原生文本输入,但可以通过结合 DOM 元素(如 input 或 textarea)与 Canvas 渲染,实现一个“看起来在 Canvas 上输入”的光标动画效果。关键不是让 Canvas 处理键盘,而是让它精准模拟光标视觉行为:位置、闪烁、跟随输入内容、响应点击和方向键移动。
光标位置需与真实输入框同步
Canvas 上的光标只是视觉代理,它的 left/top 必须实时匹配 DOM 输入框中光标的像素位置。不能靠估算,而要依赖浏览器原生能力:
- 用
input或textarea承担实际输入逻辑(含中文输入法、全选、剪切粘贴等),设为透明无边框、绝对定位、z-index 高于 Canvas; - 监听
input、click、keydown(方向键、Home/End)事件,触发位置重算; - 调用
getBoundingClientRect()+caretPositionFromPoint()(部分浏览器支持)或更可靠的getSelection().getRangeAt(0).getBoundingClientRect()获取光标矩形; - 对 textarea 换行场景,需按行拆分文本、逐行测量宽度,再累加计算光标 Y 偏移。
Canvas 光标绘制与闪烁控制
光标不是简单画一条线,它需要可定制的样式和精确的定时:
- 在 Canvas 上用
ctx.fillRect(x, y, width, height)绘制竖线,宽度通常 2px,高度取当前字体行高(可用ctx.measureText('M').width * 1.2估算); - 闪烁用
requestAnimationFrame控制,每 500ms 切换显隐状态,避免 setInterval 定时漂移; - 闪烁期间若输入框失去焦点,应立即隐藏光标;获得焦点时重置闪烁计时器;
- 支持自定义颜色、粗细、圆角、甚至带微动动画(如轻微左右晃动)提升拟真感。
鼠标点击定位光标位置
用户点击 Canvas 区域时,光标需跳转到对应字符位置,这需要坐标反查:
- 监听 Canvas 的
click事件,用event.offsetX / event.offsetY获取相对坐标; - 将该坐标映射回输入框的 client 区域(考虑滚动偏移、缩放、字体大小);
- 创建临时
span插入文本每个字符之间,用document.caretRangeFromPoint()获取最近插入点; - 或采用二分查找法:在输入框内逐字符插入
<span id="pos-0"></span>,再根据点击坐标比对各 span 的getBoundingClientRect()确定最邻近位置。
响应键盘方向键与编辑操作
方向键、Backspace、Delete 等操作会改变光标位置或内容,Canvas 光标必须即时反馈:
- 监听
keydown,对 ArrowLeft/ArrowRight/ArrowUp/ArrowDown/Home/End/Backspace/Delete 做特殊处理; - 方向键触发后,延迟一帧(
setTimeout(() => {}, 0))再读取光标位置,确保 DOM 已更新; - Backspace/Delete 后,需重新计算光标所在字符索引及对应坐标;
- 禁用默认行为(
e.preventDefault())仅限于你完全接管光标逻辑的场景;一般建议让原生输入框处理,Canvas 只做视觉同步。
不复杂但容易忽略:Canvas 光标始终是“影子”,它不能替代输入框的功能。真正可靠的做法,是把输入逻辑交给浏览器,用 Canvas 做一层轻量、高性能、可定制的视觉层——既保留兼容性,又赢得表现力。











