[Bug]: 电脑触控板双指操作时,zoom-canvas 和 drag-canvas 手势同时触发了
Describe the bug / 问题描述
复现方式是双指朝同一个方向移动:
- 移动触发了 drag-canvas 视图移动
- 两个手指间的距离会有变化,触发了 zoom-canvas 缩放
Reproduction link / 复现链接
https://g6.antv.antgroup.com/examples/behavior/canvas/#optimize
Steps to Reproduce the Bug or Issue / 重现步骤
No response
Version / 版本
Please select / 请选择
OS / 操作系统
- [x] macOS
- [ ] Windows
- [ ] Linux
- [ ] Others / 其他
Browser / 浏览器
- [x] Chrome
- [ ] Edge
- [ ] Firefox
- [ ] Safari (Limited support / 有限支持)
- [ ] IE (Nonsupport / 不支持)
- [ ] Others / 其他
这个能力目前还不支持
好的,谢谢。这个问题在 mac 上比较容易复现,触控板、鼠标都是可以双指操作的。
我暂时把缩放禁用了,只保留了平移。
看了下 sketch、蓝湖的交互表现,zoom-canvas 和 drag-canvas 预期是互斥的,就是触发了一种时,另一种不触发
@yvonneyx 看起来是个 bug,双指拉开的手势,预期是不触发 drag-canvas 事件
问了下 AI,在 macOS 触控板中,JavaScript 可通过监听 wheel 事件并结合事件对象的属性判断用户是滚动还是缩放,具体实现如下:
核心判断逻辑
- 监听
wheel事件
document.addEventListener('wheel', function(e) {
// 判断逻辑
}, { passive: false });
- 通过
ctrlKey或metaKey属性区分
- 缩放操作:触控板双指捏合会触发 wheel 事件,且 e.ctrlKey === true(即使未按下物理 Control 键)。
- 滚动操作:双指上下滑动触发 wheel 事件,e.ctrlKey === false,且 deltaY 或 deltaX 有值。
- 示例代码
document.addEventListener('wheel', function(e) {
if (e.ctrlKey || e.metaKey) {
// 缩放行为(双指捏合)
e.preventDefault(); // 可选:阻止默认缩放
console.log('缩放:', e.deltaY);
} else {
// 滚动行为(双指滑动)
console.log('滚动:', e.deltaY);
}
}, { passive: false });
问了下 AI,在 macOS 触控板中,JavaScript 可通过监听
wheel事件并结合事件对象的属性判断用户是滚动还是缩放,具体实现如下:核心判断逻辑
- 监听
wheel事件document.addEventListener('wheel', function(e) { // 判断逻辑 }, { passive: false }); 2. 通过
ctrlKey或metaKey属性区分
- 缩放操作:触控板双指捏合会触发 wheel 事件,且 e.ctrlKey === true(即使未按下物理 Control 键)。
- 滚动操作:双指上下滑动触发 wheel 事件,e.ctrlKey === false,且 deltaY 或 deltaX 有值。
- 示例代码
document.addEventListener('wheel', function(e) { if (e.ctrlKey || e.metaKey) { // 缩放行为(双指捏合) e.preventDefault(); // 可选:阻止默认缩放 console.log('缩放:', e.deltaY); } else { // 滚动行为(双指滑动) console.log('滚动:', e.deltaY); } }, { passive: false });
赞,可以在 G6 中验证下,这个需求确实还挺常见的
目前我在配置项里设置了 enable,解决了,不确定源码里怎么调整
behaviors: [
{
type: 'scroll-canvas',
enable: (event: any) => {
if (isPC()) {
// 缩放
if (event.ctrlKey || event.metaKey) return false
// 滚动
return true
} else {
return true
}
}
},
{
type: 'zoom-canvas',
enable: (event: any) => {
if (isPC()) {
// 缩放
if (event.ctrlKey || event.metaKey) return true
// 滚动
return false
} else {
return true
}
}
},
{
type: 'drag-canvas',
enable: (event: any) => {
// 阻止双指,防止来回闪烁
if (event.nativeEvent.touches?.length > 1) return false
if ('targetType' in event) return event.targetType === 'canvas'
return true
}
},
{
type: 'drag-element',
enable: (event: any) => {
// 阻止双指,防止来回闪烁
if (event.nativeEvent.touches?.length > 1) return false
return ['node', 'combo'].includes(event.targetType)
}
},
// 仅电脑端开启 hover 样式
{
type: 'hover-activate',
enable: (event: any) => isPC() && event.targetType === 'node',
state: 'active',
degree: 1,
}
]
判断 PC 电脑端的辅助函数:
const isWechatDevTools = () => {
return navigator.userAgent.toLowerCase().includes('webdebugger')
}
const isPC = () => {
const ua = navigator.userAgent
return Boolean(
!isWechatDevTools() &&
!ua.match(/mobile/ig) &&
(ua.match(/mac/ig) || ua.match(/windows/ig))
)
}
目前我在配置项里设置了 enable,解决了,不确定源码里怎么调整
behaviors: [ { type: 'scroll-canvas', enable: (event: any) => { if (isPC()) { // 缩放 if (event.ctrlKey || event.metaKey) return false // 滚动 return true
} else { return true } } }, { type: 'zoom-canvas', enable: (event: any) => { if (isPC()) { // 缩放 if (event.ctrlKey || event.metaKey) return true // 滚动 return false } else { return true } } }, { type: 'drag-canvas', enable: (event: any) => { // 阻止双指,防止来回闪烁 if (event.nativeEvent.touches?.length > 1) return false if ('targetType' in event) return event.targetType === 'canvas' return true } }, { type: 'drag-element', enable: (event: any) => { // 阻止双指,防止来回闪烁 if (event.nativeEvent.touches?.length > 1) return false return ['node', 'combo'].includes(event.targetType) } }, // 仅电脑端开启 hover 样式 { type: 'hover-activate', enable: (event: any) => isPC() && event.targetType === 'node', state: 'active', degree: 1, }] 判断 PC 电脑端的辅助函数:
const isWechatDevTools = () => { return navigator.userAgent.toLowerCase().includes('webdebugger') }
const isPC = () => { const ua = navigator.userAgent
return Boolean( !isWechatDevTools() && !ua.match(/mobile/ig) && (ua.match(/mac/ig) || ua.match(/windows/ig)) ) }
ok,学习一下,后面我提个 PR 支持