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