antvis / antvis/G6

[Bug]: 拖动节点时,执行微信截图,ctrl+alt+a快捷键,然后点击鼠标右键取消截图,框架判断拖动仍然存在

Open
#7,641 2 comments 0 reactions 0 assignees View on GitHub
waiting for maintainer
Dominant language
TypeScript
Stars
12.3k
Forks
1.6k
PR merge metrics
No merged PRs in 30d

Description

### Describe the bug / 问题描述

导致onDrag一直触发,然后重新框选节点拖动,发现节点和鼠标偏移巨大,应该是上一次拖动没有清除,问了ai,给出了方案才能解决,在onDragEnd主动执行一次resetStaleDragPlugin
```
protected onDragEnd(): void {
// 重置 @antv/g DragNDropPlugin 残留的拖拽状态
// 当 contextmenu 触发 onDragEnd 时,DragNDropPlugin 的 pointerup 未被触发,
// 导致 handlePointermove 闭包残留在 canvas 上,后续所有 pointermove 被转为 drag
this.resetStaleDragPlugin()
}

/**
* 重置 @antv/g DragNDropPlugin 残留的 pointermove 监听器
* 当外部中断(微信截图右键取消等)导致 pointerup 事件丢失时,
* DragNDropPlugin 的 handlePointermove 闭包不会被 stopDragging 清理,
* 导致后续所有 pointermove 都被转换为 drag 事件。
* 此方法在原始 pointerdown 目标上模拟 pointerupoutside 来触发 stopDragging,
* 使其调用 canvas.removeEventListener('pointermove', handlePointermove)
*/
private resetStaleDragPlugin(): void {
const target = this._dragGTarget
this._dragGTarget = null
if (!target?.emitter) return

const createMockEvent = (): any => ({
type: 'pointerupoutside',
detail: {},
target: null,
currentTarget: null,
path: null,
manager: null,
nativeEvent: null,
originalEvent: null,
defaultPrevented: false,
eventPhase: 0,
bubbles: false,
cancelBubble: false,
cancelable: false,
composed: false,
propagationStopped: false,
propagationImmediatelyStopped: false,
NONE: 0,
CAPTURING_PHASE: 1,
AT_TARGET: 2,
BUBBLING_PHASE: 3,
pointerId: 0,
width: 0,
height: 0,
isPrimary: true,
pointerType: 'mouse',
pressure: 0,
tangentialPressure: 0,
tiltX: 0,
tiltY: 0,
twist: 0,
button: 0,
buttons: 0,
altKey: false,
ctrlKey: false,
metaKey: false,
shiftKey: false,
client: { x: 0, y: 0 },
movement: { x: 0, y: 0 },
offset: { x: 0, y: 0 },
global: { x: 0, y: 0 },
screen: { x: 0, y: 0 },
canvas: { x: 0, y: 0 },
viewport: { x: 0, y: 0 },
page: { x: 0, y: 0 },
layer: { x: 0, y: 0 },
clientX: 0,
clientY: 0,
timeStamp: Date.now(),
composedPath() {
return []
},
clone() {
return createMockEvent()
},
stopPropagation() {
this.propagationStopped = true
},
stopImmediatePropagation() {
this.propagationImmediatelyStopped = true
},
preventDefault() {
this.defaultPrevented = true
}
})

try {
// dispatchToSelf=true 绕过事件传播,直接在 target.emitter 上触发
// stopDragging 监听器(注册时为 { once: true })会自动移除
target.dispatchEvent(createMockEvent(), false, true)
} catch {
// stopDragging 内部异常时静默处理(降级为原有 bug 行为,不会更糟)
}
}
```

### Reproduction link / 复现链接

_No response_

### Steps to Reproduce the Bug or Issue / 重现步骤

拖动节点时,执行微信截图,ctrl+alt+a快捷键,然后点击鼠标右键取消截图

### Version / 版本

Please select / 请选择

### OS / 操作系统

- [ ] macOS
- [x] Windows
- [ ] Linux
- [ ] Others / 其他

### Browser / 浏览器

- [x] Chrome
- [ ] Edge
- [ ] Firefox
- [ ] Safari (Limited support / 有限支持)
- [ ] IE (Nonsupport / 不支持)
- [ ] Others / 其他

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by tracing G6's onDragEnd and the @antv/g DragNDropPlugin handling for pointerup, pointermove, and pointerupoutside. Reproduce the Windows Chrome sequence with a dragged node and a cancelled WeChat screenshot, then verify that later node drags no longer trigger stale onDrag events or show a large cursor offset.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
data-visualization
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.