You need to enable JavaScript to run this app. Angular9结合fabricjs、hammerjs单击生成IText无法唤起iOS键盘如何解决
优惠活动
大模型
产品
解决方案
定价
更多

Angular9结合fabricjs、hammerjs单击生成IText无法唤起iOS键盘如何解决

根因说明

iOS 端 WebView 有安全策略限制:仅允许在用户主动触发的原生交互事件(touchstart/click等)的同步执行栈内调用输入元素的focus()方法唤起键盘,所有异步执行(包括setTimeout、事件封装库的延迟回调)的focus()调用都会被系统拦截。
你遇到的问题核心是Hammer.js的tap事件为了区分单击/双击、防误触,默认有300ms左右的触发延迟,回调执行时已经脱离了用户交互的同步上下文,所以你的focus逻辑全部被iOS拦截了。

可行解决方案

方案1:替换Hammer.js的tap事件为原生触摸事件判断(最稳定)

自己监听原生touchstart+touchend事件模拟单击逻辑,在原生事件的同步回调内执行IText创建和焦点唤起逻辑:

// Angular组件内的监听逻辑
let touchStartTime = 0;
let touchStartX = 0;
let touchStartY = 0;
const canvasEl = document.getElementById('你的canvas容器ID');

canvasEl.addEventListener('touchstart', (e) => {
  touchStartTime = Date.now();
  touchStartX = e.touches[0].clientX;
  touchStartY = e.touches[0].clientY;
});

canvasEl.addEventListener('touchend', (e) => {
  // 符合单击判定:触摸时长<300ms,位移<10px
  if (Date.now() - touchStartTime < 300 
    && Math.abs(e.changedTouches[0].clientX - touchStartX) < 10
    && Math.abs(e.changedTouches[0].clientY - touchStartY) < 10) {
    // 阻止默认行为避免双击缩放
    e.preventDefault();
    // 同步创建IText
    const text = new fabric.IText('输入文本', {
      left: 100,
      top: 100,
      fontSize: 24
    });
    canvas.add(text);
    canvas.setActiveObject(text);
    // 同步唤起编辑,不需要加setTimeout
    text.enterEditing();
    text.hiddenTextarea.focus();
  }
});

方案2:调整Hammer.js配置消除tap延迟(如果必须用Hammer的tap)

禁用Hammer的doubletap识别器,消除tap事件的触发延迟,确保回调在同步上下文执行:

const hammer = new Hammer(canvasEl);
// 先禁用doubletap识别器,避免tap事件等待双击判定
hammer.get('doubletap').set({ enable: false });
// 把tap的识别阈值降到最低
hammer.get('tap').set({
  threshold: 10,
  time: 250
});

hammer.on('tap', (e) => {
  // 这里的回调现在会同步触发,直接执行IText创建和focus逻辑即可
  const text = new fabric.IText('输入文本', {
    left: e.center.x,
    top: e.center.y,
    fontSize: 24
  });
  canvas.add(text);
  canvas.setActiveObject(text);
  text.enterEditing();
  text.hiddenTextarea.focus();
});

补充适配点

如果以上方案还是不生效,可以加一个前置兼容处理:在页面初始化时提前插入一个永久透明的textarea,在用户交互的最开始先focus这个提前存在的textarea,再转移焦点到fabric的hiddenTextarea:

/* 全局样式 */
.pre-textarea {
  position: fixed;
  opacity: 0;
  left: -100px;
  top: -100px;
  z-index: -1;
}
// 在交互回调的最开头同步执行
document.querySelector<HTMLTextAreaElement>('.pre-textarea').focus();
// 再执行fabric的focus逻辑
text.hiddenTextarea.focus();

内容的提问来源于stack exchange,提问作者Jivan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.18 09:06:04