Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(behaviors): drag-element can set pointer cursor #5827

Merged
merged 4 commits into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion packages/g6/__tests__/unit/behaviors/drag-element.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { behaviorDragNode } from '@/__tests__/demos';
import type { Graph } from '@/src';
import { ComboEvent, NodeEvent } from '@/src';
import { ComboEvent, CommonEvent, NodeEvent } from '@/src';
import { createDemoGraph } from '@@/utils';

describe('behavior drag element', () => {
Expand All @@ -14,11 +14,28 @@ describe('behavior drag element', () => {
graph.destroy();
});

it('pointer cursor', () => {
graph.emit(NodeEvent.POINTER_ENTER, {
target: { id: 'node-4' },
targetType: 'node',
type: CommonEvent.POINTER_ENTER,
});
expect(graph.getCanvas().getConfig().cursor).toBe('grab');

graph.emit(NodeEvent.POINTER_LEAVE, {
target: { id: 'node-4' },
targetType: 'node',
type: CommonEvent.POINTER_LEAVE,
});
expect(graph.getCanvas().getConfig().cursor).toBe('default');
});

it('default status', async () => {
await expect(graph).toMatchSnapshot(__filename);

graph.emit(NodeEvent.DRAG_START, { target: { id: 'node-4' }, targetType: 'node' });
graph.emit(NodeEvent.DRAG, { dx: 20, dy: 20 });
expect(graph.getCanvas().getConfig().cursor).toBe('grabbing');
graph.emit(NodeEvent.DRAG_END);

await expect(graph).toMatchSnapshot(__filename, 'after-drag');
Expand Down
63 changes: 57 additions & 6 deletions packages/g6/src/behaviors/drag-element.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { BaseStyleProps } from '@antv/g';
import type { BaseStyleProps, Cursor } from '@antv/g';
import { Rect } from '@antv/g';
import { isFunction } from '@antv/util';
import { COMBO_KEY, CanvasEvent, ComboEvent, CommonEvent } from '../constants';
import type { RuntimeContext } from '../runtime/types';
import type { EdgeDirection, ID, IElementDragEvent, Point, Prefix, State } from '../types';
import type { EdgeDirection, ID, IElementDragEvent, IPointerEvent, Point, Prefix, State } from '../types';
import { getBBoxSize, getCombinedBBox } from '../utils/bbox';
import { idOf } from '../utils/id';
import { subStyleProps } from '../utils/prefix';
Expand Down Expand Up @@ -88,6 +88,31 @@ export interface DragElementOptions extends BaseBehaviorOptions, Prefix<'shadow'
* <en/> Callback when dragging is completed
*/
onFinish?: (ids: ID[]) => void;
/**
* <zh/> 指针样式
*
* <en/> Cursor style
*/
cursor?: {
/**
* <zh/> 默认指针样式
*
* <en/> Default cursor style
*/
default?: Cursor;
/**
* <zh/> 可抓取指针样式
*
* <en/> Cursor style that can be grabbed
*/
grab: Cursor;
/**
* <zh/> 抓取中指针样式
*
* <en/> Cursor style when grabbing
*/
grabbing: Cursor;
};
}

/**
Expand All @@ -109,6 +134,11 @@ export class DragElement extends BaseBehavior<DragElementOptions> {
shadowStroke: '#1890FF',
shadowStrokeOpacity: 0.9,
shadowLineDash: [5, 5],
cursor: {
default: 'default',
grab: 'grab',
grabbing: 'grabbing',
},
};

protected enable: boolean = false;
Expand All @@ -123,6 +153,8 @@ export class DragElement extends BaseBehavior<DragElementOptions> {

private hiddenEdges: ID[] = [];

private isDragging: boolean = false;

private get animation() {
if (!this.options.shadow) return false;
return this.options.animation;
Expand All @@ -145,18 +177,19 @@ export class DragElement extends BaseBehavior<DragElementOptions> {
* @internal
*/
public update(options: Partial<DragElementOptions>): void {
this.unbindEvents();
super.update(options);
this.bindEvents();
}

private bindEvents() {
const { graph } = this.context;
this.unbindEvents();

this.enableElements.forEach((type) => {
graph.on(`${type}:${CommonEvent.DRAG_START}`, this.onDragStart);
graph.on(`${type}:${CommonEvent.DRAG}`, this.onDrag);
graph.on(`${type}:${CommonEvent.DRAG_END}`, this.onDragEnd);
graph.on(`${type}:${CommonEvent.POINTER_ENTER}`, this.setCursor);
graph.on(`${type}:${CommonEvent.POINTER_LEAVE}`, this.setCursor);
});

if (['link'].includes(this.options.dropEffect)) {
Expand Down Expand Up @@ -206,7 +239,10 @@ export class DragElement extends BaseBehavior<DragElementOptions> {
this.enable = this.validate(event);
if (!this.enable) return;

this.context.batch?.startBatch();
const { batch, canvas } = this.context;
canvas.setCursor(this.options!.cursor?.grabbing || 'grabbing');
this.isDragging = true;
batch!.startBatch();
this.target = this.getSelectedNodeIDs([event.target.id]);
this.hideEdge();
this.context.graph.frontElement(this.target);
Expand Down Expand Up @@ -245,7 +281,10 @@ export class DragElement extends BaseBehavior<DragElementOptions> {
}
this.showEdges();
this.options.onFinish?.(this.target);
this.context.batch?.endBatch();
const { batch, canvas } = this.context;
batch!.endBatch();
canvas.setCursor(this.options!.cursor?.grab || 'grab');
this.isDragging = false;
this.target = [];
}

Expand All @@ -271,6 +310,16 @@ export class DragElement extends BaseBehavior<DragElementOptions> {
await element?.draw({ animation: true })?.finished;
};

private setCursor = (event: IPointerEvent) => {
if (this.isDragging) return;
const { type } = event;
const { canvas } = this.context;
const { cursor } = this.options;

if (type === CommonEvent.POINTER_ENTER) canvas.setCursor(cursor?.grab || 'grab');
else canvas.setCursor(cursor?.default || 'default');
};

/**
* <zh/> 验证元素是否允许拖拽
*
Expand Down Expand Up @@ -373,6 +422,8 @@ export class DragElement extends BaseBehavior<DragElementOptions> {
graph.off(`${type}:${CommonEvent.DRAG_START}`, this.onDragStart);
graph.off(`${type}:${CommonEvent.DRAG}`, this.onDrag);
graph.off(`${type}:${CommonEvent.DRAG_END}`, this.onDragEnd);
graph.off(`${type}:${CommonEvent.POINTER_ENTER}`, this.setCursor);
graph.off(`${type}:${CommonEvent.POINTER_LEAVE}`, this.setCursor);
});

graph.off(`combo:${CommonEvent.DROP}`, this.onDrop);
Expand Down
21 changes: 15 additions & 6 deletions packages/g6/src/runtime/behavior.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export class BehaviorController extends ExtensionController<BaseBehavior<CustomB
*/
private currentTarget: Target | null = null;

private currentTargetType: string | null = null;

public category = 'behavior' as const;

constructor(context: RuntimeContext) {
Expand Down Expand Up @@ -74,13 +76,19 @@ export class BehaviorController extends ExtensionController<BaseBehavior<CustomB
if (type === CommonEvent.POINTER_MOVE) {
if (this.currentTarget !== targetElement) {
if (this.currentTarget) {
graph.emit(`${targetType}:${CommonEvent.POINTER_LEAVE}`, { ...stdEvent, target: this.currentTarget });
graph.emit(`${this.currentTargetType}:${CommonEvent.POINTER_LEAVE}`, {
...stdEvent,
type: CommonEvent.POINTER_LEAVE,
target: this.currentTarget,
});
}
if (targetElement) {
Object.assign(stdEvent, { type: CommonEvent.POINTER_ENTER });
graph.emit(`${targetType}:${CommonEvent.POINTER_ENTER}`, stdEvent);
}
}
this.currentTarget = targetElement;
this.currentTargetType = targetType;
}

// 非右键点击事件 / Click event except right click
Expand All @@ -91,22 +99,23 @@ export class BehaviorController extends ExtensionController<BaseBehavior<CustomB

// 双击事件 / Double click event
if (type === CommonEvent.CLICK && detail === 2) {
Object.assign(stdEvent, { type: CommonEvent.DBLCLICK });
graph.emit(`${targetType}:${CommonEvent.DBLCLICK}`, stdEvent);
graph.emit(CommonEvent.DBLCLICK, stdEvent);
}

// 右键菜单 / Contextmenu
if (type === CommonEvent.POINTER_DOWN && button === 2) {
const contextMenuEvent = {
...stdEvent,
Object.assign(stdEvent, {
type: CommonEvent.CONTEXT_MENU,
preventDefault: () => {
canvas.getContainer()?.addEventListener(CommonEvent.CONTEXT_MENU, (e) => e.preventDefault(), {
once: true,
});
},
};
graph.emit(`${targetType}:${CommonEvent.CONTEXT_MENU}`, contextMenuEvent);
graph.emit(CommonEvent.CONTEXT_MENU, contextMenuEvent);
});
graph.emit(`${targetType}:${CommonEvent.CONTEXT_MENU}`, stdEvent);
graph.emit(CommonEvent.CONTEXT_MENU, stdEvent);
}
};

Expand Down
1 change: 1 addition & 0 deletions packages/g6/src/runtime/canvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ export class Canvas {
}

public setCursor(cursor: Cursor) {
this.config.cursor = cursor;
Object.values(this.canvas).forEach((canvas) => {
canvas.setCursor(cursor);
});
Expand Down
Loading