diff --git a/packages/g6/__tests__/bugs/focus-element.spec.ts b/packages/g6/__tests__/bugs/focus-element.spec.ts index 4886a70a804..f251910704c 100644 --- a/packages/g6/__tests__/bugs/focus-element.spec.ts +++ b/packages/g6/__tests__/bugs/focus-element.spec.ts @@ -1,5 +1,5 @@ -import { CanvasEvent, CommonEvent, NodeEvent } from '@/src'; -import { createGraph } from '@@/utils'; +import { CommonEvent, NodeEvent } from '@/src'; +import { createGraph, dispatchCanvasEvent } from '@@/utils'; describe('focus element', () => { it('focus after drag', async () => { @@ -17,9 +17,9 @@ describe('focus element', () => { await graph.draw(); - graph.emit(CanvasEvent.DRAG_START, { targetType: 'canvas' }); - graph.emit(CanvasEvent.DRAG, { movement: { x: 100, y: 100 }, targetType: 'canvas' }); - graph.emit(CanvasEvent.DRAG_END); + dispatchCanvasEvent(graph, CommonEvent.DRAG_START, { targetType: 'canvas' }); + dispatchCanvasEvent(graph, CommonEvent.DRAG, { movement: { x: 100, y: 100 }, targetType: 'canvas' }); + dispatchCanvasEvent(graph, CommonEvent.DRAG_END); await expect(graph).toMatchSnapshot(__filename, 'focus-before-drag'); diff --git a/packages/g6/__tests__/snapshots/behaviors/drag-canvas/drag-on-element-default.svg b/packages/g6/__tests__/snapshots/behaviors/drag-canvas/drag-on-element-default.svg new file mode 100644 index 00000000000..e945b86c6d5 --- /dev/null +++ b/packages/g6/__tests__/snapshots/behaviors/drag-canvas/drag-on-element-default.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/g6/__tests__/snapshots/behaviors/drag-canvas/drag-on-element.svg b/packages/g6/__tests__/snapshots/behaviors/drag-canvas/drag-on-element.svg new file mode 100644 index 00000000000..825a6f702ec --- /dev/null +++ b/packages/g6/__tests__/snapshots/behaviors/drag-canvas/drag-on-element.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/g6/__tests__/unit/behaviors/drag-canvas.spec.ts b/packages/g6/__tests__/unit/behaviors/drag-canvas.spec.ts index a0806703094..87bb8cbac93 100644 --- a/packages/g6/__tests__/unit/behaviors/drag-canvas.spec.ts +++ b/packages/g6/__tests__/unit/behaviors/drag-canvas.spec.ts @@ -1,7 +1,7 @@ import { behaviorDragCanvas } from '@/__tests__/demos'; import type { Graph } from '@/src'; -import { CanvasEvent, CommonEvent } from '@/src'; -import { createDemoGraph, sleep } from '@@/utils'; +import { CommonEvent } from '@/src'; +import { createDemoGraph, createGraph, dispatchCanvasEvent, sleep } from '@@/utils'; describe('behavior drag canvas', () => { let graph: Graph; @@ -61,9 +61,11 @@ describe('behavior drag canvas', () => { it('drag', () => { const [x, y] = graph.getPosition(); - graph.emit(CanvasEvent.DRAG_START, { targetType: 'canvas' }); - graph.emit(CanvasEvent.DRAG, { movement: { x: 10, y: 10 }, targetType: 'canvas' }); - graph.emit(CanvasEvent.DRAG_END); + + dispatchCanvasEvent(graph, CommonEvent.DRAG_START, { targetType: 'canvas' }); + dispatchCanvasEvent(graph, CommonEvent.DRAG, { movement: { x: 10, y: 10 }, targetType: 'canvas' }); + dispatchCanvasEvent(graph, CommonEvent.DRAG_END); + expect(graph.getPosition()).toBeCloseTo([x + 10, y + 10]); }); @@ -105,9 +107,34 @@ describe('behavior drag canvas', () => { const onFinish = jest.fn(); graph.updateBehavior({ key: 'drag-canvas', trigger: 'drag', onFinish }); - graph.emit(CanvasEvent.DRAG_START, { targetType: 'canvas' }); - graph.emit(CanvasEvent.DRAG, { movement: { x: 10, y: 10 }, targetType: 'canvas' }); - graph.emit(CanvasEvent.DRAG_END); + dispatchCanvasEvent(graph, CommonEvent.DRAG_START, { targetType: 'canvas' }); + dispatchCanvasEvent(graph, CommonEvent.DRAG, { movement: { x: 10, y: 10 }, targetType: 'canvas' }); + dispatchCanvasEvent(graph, CommonEvent.DRAG_END); + expect(onFinish).toHaveBeenCalledTimes(1); }); + + it('trigger on element', async () => { + const graph = createGraph({ + data: { + nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }], + }, + node: { + style: { + size: 20, + }, + }, + behaviors: [{ type: 'drag-canvas', enable: true }], + }); + + await graph.draw(); + + await expect(graph).toMatchSnapshot(__filename, 'drag-on-element-default'); + + dispatchCanvasEvent(graph, CommonEvent.DRAG_START, { targetType: 'node' }); + dispatchCanvasEvent(graph, CommonEvent.DRAG, { movement: { x: -50, y: -50 }, targetType: 'node' }); + dispatchCanvasEvent(graph, CommonEvent.DRAG_END); + + await expect(graph).toMatchSnapshot(__filename, 'drag-on-element'); + }); }); diff --git a/packages/g6/__tests__/utils/canvas.ts b/packages/g6/__tests__/utils/canvas.ts new file mode 100644 index 00000000000..2d946a13e38 --- /dev/null +++ b/packages/g6/__tests__/utils/canvas.ts @@ -0,0 +1,8 @@ +import type { Graph } from '@/src'; +import { CustomEvent } from '@antv/g'; + +export function dispatchCanvasEvent(graph: Graph, type: string, data?: any) { + // @ts-expect-error private method + const canvas = graph.context.canvas.document; + canvas.dispatchEvent(new CustomEvent(type, data)); +} diff --git a/packages/g6/__tests__/utils/index.ts b/packages/g6/__tests__/utils/index.ts index d21dfbe396e..46185c73a20 100644 --- a/packages/g6/__tests__/utils/index.ts +++ b/packages/g6/__tests__/utils/index.ts @@ -1,3 +1,4 @@ +export { dispatchCanvasEvent } from './canvas'; export { createDemoGraph, createEdgeNode, createGraph, createGraphCanvas } from './create'; export { createDeterministicRandom } from './random'; export { sleep } from './sleep'; diff --git a/packages/g6/src/behaviors/drag-canvas.ts b/packages/g6/src/behaviors/drag-canvas.ts index 8d7ae5f548d..c7bb940116b 100644 --- a/packages/g6/src/behaviors/drag-canvas.ts +++ b/packages/g6/src/behaviors/drag-canvas.ts @@ -1,6 +1,6 @@ import type { Cursor } from '@antv/g'; -import { debounce, isFunction, isObject } from '@antv/util'; -import { CanvasEvent } from '../constants'; +import { debounce, isObject } from '@antv/util'; +import { CanvasEvent, CommonEvent } from '../constants'; import type { RuntimeContext } from '../runtime/types'; import type { IKeyboardEvent, IPointerEvent, Vector2, ViewportAnimationEffectTiming } from '../types'; import type { ShortcutKey } from '../utils/shortcut'; @@ -61,7 +61,10 @@ export interface DragCanvasOptions extends BaseBehaviorOptions { */ export class DragCanvas extends BaseBehavior { static defaultOptions: Partial = { - enable: true, + enable: (event) => { + if ('targetType' in event) return event.targetType === 'canvas'; + return true; + }, sensitivity: 10, }; @@ -69,6 +72,10 @@ export class DragCanvas extends BaseBehavior { private defaultCursor: Cursor; + private get canvas() { + return this.context.canvas.getLayer(); + } + constructor(context: RuntimeContext, options: DragCanvasOptions) { super(context, Object.assign({}, DragCanvas.defaultOptions, options)); @@ -93,19 +100,18 @@ export class DragCanvas extends BaseBehavior { private bindEvents() { const { trigger } = this.options; - const { graph } = this.context; if (isObject(trigger)) { const { up = [], down = [], left = [], right = [] } = trigger; - this.shortcut.bind(up, (event) => this.onTranslate([0, 1], event)); this.shortcut.bind(down, (event) => this.onTranslate([0, -1], event)); this.shortcut.bind(left, (event) => this.onTranslate([1, 0], event)); this.shortcut.bind(right, (event) => this.onTranslate([-1, 0], event)); } else { - graph.on(CanvasEvent.DRAG_START, this.onDragStart); - graph.on(CanvasEvent.DRAG, this.onDrag); - graph.on(CanvasEvent.DRAG_END, this.onDragEnd); + const canvas = this.canvas; + canvas.addEventListener(CommonEvent.DRAG_START, this.onDragStart); + canvas.addEventListener(CommonEvent.DRAG, this.onDrag); + canvas.addEventListener(CommonEvent.DRAG_END, this.onDragEnd); } } @@ -113,7 +119,6 @@ export class DragCanvas extends BaseBehavior { private onDragStart = (event: IPointerEvent) => { if (!this.validate(event)) return; - if (event.targetType !== 'canvas') return; this.isDragging = true; this.context.canvas.setCursor('grabbing'); }; @@ -160,16 +165,16 @@ export class DragCanvas extends BaseBehavior { private validate(event: IPointerEvent | IKeyboardEvent) { if (this.destroyed) return false; const { enable } = this.options; - if (isFunction(enable)) return enable(event); + if (typeof enable === 'function') return enable(event); return !!enable; } private unbindEvents() { this.shortcut.unbindAll(); - const { graph } = this.context; - graph.off(CanvasEvent.DRAG_START, this.onDragStart); - graph.off(CanvasEvent.DRAG, this.onDrag); - graph.off(CanvasEvent.DRAG_END, this.onDragEnd); + const canvas = this.canvas; + canvas.removeEventListener(CanvasEvent.DRAG_START, this.onDragStart); + canvas.removeEventListener(CanvasEvent.DRAG, this.onDrag); + canvas.removeEventListener(CanvasEvent.DRAG_END, this.onDragEnd); } public destroy(): void {