Fabric.js移动端画布无法同时支持滚动与对象点击问题求助
解决Fabric.js移动端画布滚动与对象点击冲突问题
问题原因
Fabric.js的allowTouchScrolling配置在触摸画布内对象时,会优先捕获触摸事件,阻止容器的滚动默认行为,导致无法同时实现滚动和点击操作。
解决方案
通过手动区分滚动手势和点击手势,结合事件监听实现两者共存:
1. 优化CSS滚动体验
给容器添加移动端弹性滚动属性,提升滚动顺滑度:
@media (max-width:600px) { .hall-canvas { overflow: auto; width: 390px; height: 800px; margin-bottom: 20px; -webkit-overflow-scrolling: touch; /* 开启移动端弹性滚动 */ } }
2. 自定义触摸事件处理
保留原有Canvas配置,添加触摸事件监听来区分滚动和点击:
const hall = new fabric.Canvas('hall', { backgroundColor:'#AACFE1', selection: false, width: 2000, height: 1500, controlsAboveOverlay: true, centeredScaling: true, allowTouchScrolling: true }); let touchStartX = 0; let touchStartY = 0; const scrollThreshold = 10; // 超过此距离判定为滚动 // 记录触摸起始位置 document.querySelector('.hall-canvas').addEventListener('touchstart', (e) => { touchStartX = e.touches[0].clientX; touchStartY = e.touches[0].clientY; }, { passive: true }); // 不阻止默认滚动行为 // 判断是否为滚动手势 hall.on('touch:move', (e) => { const touchX = e.e.touches[0].clientX; const touchY = e.e.touches[0].clientY; const deltaX = Math.abs(touchX - touchStartX); const deltaY = Math.abs(touchY - touchStartY); if (deltaX > scrollThreshold || deltaY > scrollThreshold) { hall._isScrolling = true; } }); // 处理触摸结束,触发点击或忽略 hall.on('touch:end', (e) => { if (hall._isScrolling) { hall._isScrolling = false; return; } const target = e.target; if (target && target !== hall) { // 这里添加你的对象点击逻辑 console.log('对象被点击:', target); // 示例:给点击对象添加高亮效果 target.set('fill', '#ff0000'); hall.renderAll(); } });
关键说明
passive: true:确保触摸起始事件不阻止浏览器的默认滚动行为,让容器能正常响应滚动。- 滚动阈值:通过判断触摸移动距离,区分滚动(长距离移动)和点击(短距离/无移动),避免误触发。
-webkit-overflow-scrolling: touch:优化iOS设备的滚动体验,实现弹性滚动效果。
内容的提问来源于stack exchange,提问作者Hai Elimelech
相关产品推荐
相关产品推荐

