mirror of
https://gitee.com/antv/g6.git
synced 2024-11-30 02:38:20 +08:00
fix: fix issue where drag elements under non-default zoom values was abnormal (#5583)
* refactor(behaviors): remove draggableElement of drag-element * fix(behaviors): fix drag element error when not on default zoom
This commit is contained in:
parent
f451672c7a
commit
b57cdfb912
@ -31,7 +31,7 @@ export const behaviorDragNode: STDTestCase = async (context) => {
|
||||
behaviorDragNode.form = (panel) => {
|
||||
const config = {
|
||||
enable: true,
|
||||
hideEdges: 'none',
|
||||
hideEdge: 'none',
|
||||
shadow: false,
|
||||
};
|
||||
const handleChange = () => {
|
||||
@ -39,7 +39,7 @@ export const behaviorDragNode: STDTestCase = async (context) => {
|
||||
};
|
||||
return [
|
||||
panel.add(config, 'enable').onChange(handleChange),
|
||||
panel.add(config, 'hideEdges', ['none', 'in', 'out', 'both']).onChange(handleChange),
|
||||
panel.add(config, 'hideEdge', ['none', 'in', 'out', 'both']).onChange(handleChange),
|
||||
panel.add(config, 'shadow').onChange(handleChange),
|
||||
];
|
||||
};
|
||||
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
@ -1,4 +1,5 @@
|
||||
import { CommonEvent, type Graph } from '@/src';
|
||||
import type { Graph } from '@/src';
|
||||
import { CommonEvent } from '@/src';
|
||||
import { behaviorDragNode } from '@@/demo/case';
|
||||
import { createDemoGraph } from '@@/utils';
|
||||
|
||||
@ -20,22 +21,22 @@ describe('behavior drag element', () => {
|
||||
});
|
||||
|
||||
it('hide edges', async () => {
|
||||
graph.setBehaviors([{ type: 'drag-element', hideEdges: 'both' }]);
|
||||
graph.setBehaviors([{ type: 'drag-element', hideEdge: 'both' }]);
|
||||
graph.emit(`node:${CommonEvent.DRAG_START}`, { target: { id: 'node-4' }, targetType: 'node' });
|
||||
graph.emit(`node:${CommonEvent.DRAG}`, { dx: 20, dy: 20 });
|
||||
await expect(graph).toMatchSnapshot(__filename, 'hideEdges-both');
|
||||
await expect(graph).toMatchSnapshot(__filename, 'hideEdge-both');
|
||||
graph.emit(`node:${CommonEvent.DRAG_END}`);
|
||||
|
||||
graph.setBehaviors([{ type: 'drag-element', hideEdges: 'in' }]);
|
||||
graph.setBehaviors([{ type: 'drag-element', hideEdge: 'in' }]);
|
||||
graph.emit(`node:${CommonEvent.DRAG_START}`, { target: { id: 'node-3' }, targetType: 'node' });
|
||||
graph.emit(`node:${CommonEvent.DRAG}`, { dx: 0, dy: 20 });
|
||||
await expect(graph).toMatchSnapshot(__filename, 'hideEdges-in');
|
||||
await expect(graph).toMatchSnapshot(__filename, 'hideEdge-in');
|
||||
graph.emit(`node:${CommonEvent.DRAG_END}`);
|
||||
|
||||
graph.setBehaviors([{ type: 'drag-element', hideEdges: 'out' }]);
|
||||
graph.setBehaviors([{ type: 'drag-element', hideEdge: 'out' }]);
|
||||
graph.emit(`node:${CommonEvent.DRAG_START}`, { target: { id: 'node-3' }, targetType: 'node' });
|
||||
graph.emit(`node:${CommonEvent.DRAG}`, { dx: 0, dy: 20 });
|
||||
await expect(graph).toMatchSnapshot(__filename, 'hideEdges-out');
|
||||
await expect(graph).toMatchSnapshot(__filename, 'hideEdge-out');
|
||||
graph.emit(`node:${CommonEvent.DRAG_END}`);
|
||||
});
|
||||
|
||||
|
@ -0,0 +1,40 @@
|
||||
import { Graph } from '@/src';
|
||||
import { positionOf } from '@/src/utils/position';
|
||||
import { createGraphCanvas } from '@@/utils';
|
||||
|
||||
describe('behavior drag element bug', () => {
|
||||
it('drag on non-default zoom', async () => {
|
||||
const graph = new Graph({
|
||||
animation: false,
|
||||
container: createGraphCanvas(document.getElementById('container')),
|
||||
data: {
|
||||
nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],
|
||||
},
|
||||
behaviors: ['drag-element'],
|
||||
});
|
||||
|
||||
await graph.draw();
|
||||
|
||||
expect(graph.getZoom()).toBe(1);
|
||||
expect(positionOf(graph.getNodeData('node-1'))).toEqual([100, 100, 0]);
|
||||
|
||||
graph.emit('node:dragstart', { target: { id: 'node-1' }, targetType: 'node' });
|
||||
graph.emit('node:drag', { dx: 20, dy: 20 });
|
||||
graph.emit('node:dragend');
|
||||
expect(positionOf(graph.getNodeData('node-1'))).toEqual([120, 120, 0]);
|
||||
|
||||
graph.zoomTo(2);
|
||||
graph.emit('node:dragstart', { target: { id: 'node-1' }, targetType: 'node' });
|
||||
graph.emit('node:drag', { dx: 20, dy: 20 });
|
||||
graph.emit('node:dragend');
|
||||
expect(positionOf(graph.getNodeData('node-1'))).toEqual([130, 130, 0]);
|
||||
|
||||
graph.zoomTo(0.5);
|
||||
graph.emit('node:dragstart', { target: { id: 'node-1' }, targetType: 'node' });
|
||||
graph.emit('node:drag', { dx: 20, dy: 20 });
|
||||
graph.emit('node:dragend');
|
||||
expect(positionOf(graph.getNodeData('node-1'))).toEqual([170, 170, 0]);
|
||||
|
||||
graph.destroy();
|
||||
});
|
||||
});
|
@ -8,7 +8,7 @@ import type { BehaviorEvent, EdgeDirection, Point, PrefixObject } from '../types
|
||||
import { getBBoxSize, getCombinedBBox } from '../utils/bbox';
|
||||
import { idOf } from '../utils/id';
|
||||
import { subStyleProps } from '../utils/prefix';
|
||||
import { subtract } from '../utils/vector';
|
||||
import { divide, subtract } from '../utils/vector';
|
||||
import type { BaseBehaviorOptions } from './base-behavior';
|
||||
import { BaseBehavior } from './base-behavior';
|
||||
|
||||
@ -25,12 +25,6 @@ export interface DragElementOptions extends BaseBehaviorOptions, PrefixObject<Ba
|
||||
* <en/> Whether to enable the function of dragging the node
|
||||
*/
|
||||
enable?: boolean | ((event: BehaviorEvent<FederatedMouseEvent> | BehaviorEvent<KeyboardEvent>) => boolean);
|
||||
/**
|
||||
* <zh/> 支持拖拽的元素类型
|
||||
*
|
||||
* <en/> Supported element types for dragging
|
||||
*/
|
||||
draggableElement: ('node' | 'combo')[];
|
||||
/**
|
||||
* <zh/> 拖拽操作效果
|
||||
* - link: 将拖拽元素置入为目标元素的子元素
|
||||
@ -72,7 +66,7 @@ export interface DragElementOptions extends BaseBehaviorOptions, PrefixObject<Ba
|
||||
*
|
||||
* <en/> Edges will not be hidden when using the drag shadow
|
||||
*/
|
||||
hideEdges?: 'none' | 'all' | EdgeDirection;
|
||||
hideEdge?: 'none' | 'all' | EdgeDirection;
|
||||
/**
|
||||
* <zh/> 是否启用幽灵节点,即用一个图形代替节点跟随鼠标移动
|
||||
*
|
||||
@ -84,17 +78,16 @@ export interface DragElementOptions extends BaseBehaviorOptions, PrefixObject<Ba
|
||||
*
|
||||
* <en/> Callback when dragging is completed
|
||||
*/
|
||||
onfinish?: (ids: ID[]) => void;
|
||||
onFinish?: (ids: ID[]) => void;
|
||||
}
|
||||
|
||||
export class DragElement extends BaseBehavior<DragElementOptions> {
|
||||
static defaultOptions: Partial<DragElementOptions> = {
|
||||
animation: true,
|
||||
enable: true,
|
||||
draggableElement: ['node', 'combo'],
|
||||
enable: (event) => ['node', 'combo'].includes(event.targetType),
|
||||
dropEffect: 'move',
|
||||
state: 'selected',
|
||||
hideEdges: 'none',
|
||||
hideEdge: 'none',
|
||||
shadowZIndex: 100,
|
||||
shadowFill: '#F3F9FF',
|
||||
shadowFillOpacity: 0.5,
|
||||
@ -105,6 +98,8 @@ export class DragElement extends BaseBehavior<DragElementOptions> {
|
||||
|
||||
private enable: boolean = false;
|
||||
|
||||
private enableElements = ['node', 'combo'];
|
||||
|
||||
private target: ID[] = [];
|
||||
|
||||
private shadow?: Rect;
|
||||
@ -118,10 +113,6 @@ export class DragElement extends BaseBehavior<DragElementOptions> {
|
||||
return this.options.animation;
|
||||
}
|
||||
|
||||
private get element() {
|
||||
return new Set<string>(this.options.draggableElement);
|
||||
}
|
||||
|
||||
constructor(context: RuntimeContext, options: DragElementOptions) {
|
||||
super(context, Object.assign({}, DragElement.defaultOptions, options));
|
||||
this.bindEvents();
|
||||
@ -136,7 +127,7 @@ export class DragElement extends BaseBehavior<DragElementOptions> {
|
||||
const { graph } = this.context;
|
||||
this.unbindEvents();
|
||||
|
||||
this.element.forEach((type) => {
|
||||
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);
|
||||
@ -164,17 +155,19 @@ export class DragElement extends BaseBehavior<DragElementOptions> {
|
||||
if (!this.enable) return;
|
||||
|
||||
this.target = this.getSelectedNodeIDs([event.target.id]);
|
||||
this.hideEdges();
|
||||
this.hideEdge();
|
||||
this.context.graph.frontElement(this.target);
|
||||
if (this.options.shadow) this.createShadow(this.target);
|
||||
};
|
||||
|
||||
private onDrag = (event: DragEvent) => {
|
||||
if (!this.enable) return;
|
||||
const zoom = this.context.graph.getZoom();
|
||||
const { dx, dy } = event;
|
||||
const delta = divide([dx, dy], zoom);
|
||||
|
||||
if (this.options.shadow) this.moveShadow([dx, dy]);
|
||||
else this.moveElement(this.target, [dx, dy]);
|
||||
if (this.options.shadow) this.moveShadow(delta);
|
||||
else this.moveElement(this.target, delta);
|
||||
};
|
||||
|
||||
private onDragEnd = () => {
|
||||
@ -187,7 +180,7 @@ export class DragElement extends BaseBehavior<DragElementOptions> {
|
||||
this.moveElement(this.target, [dx, dy]);
|
||||
}
|
||||
this.showEdges();
|
||||
this.options.onfinish?.(this.target);
|
||||
this.options.onFinish?.(this.target);
|
||||
this.target = [];
|
||||
};
|
||||
|
||||
@ -209,7 +202,6 @@ export class DragElement extends BaseBehavior<DragElementOptions> {
|
||||
|
||||
private validate(event: DragEvent) {
|
||||
if (this.destroyed) return false;
|
||||
if (!this.element.has(event.targetType)) return false;
|
||||
const { enable } = this.options;
|
||||
if (isFunction(enable)) return enable(event);
|
||||
return !!enable;
|
||||
@ -270,14 +262,14 @@ export class DragElement extends BaseBehavior<DragElementOptions> {
|
||||
this.hiddenEdges = [];
|
||||
}
|
||||
|
||||
private hideEdges() {
|
||||
const { hideEdges, shadow } = this.options;
|
||||
if (hideEdges === 'none' || shadow) return;
|
||||
private hideEdge() {
|
||||
const { hideEdge, shadow } = this.options;
|
||||
if (hideEdge === 'none' || shadow) return;
|
||||
const { graph } = this.context;
|
||||
if (hideEdges === 'all') this.hiddenEdges = graph.getEdgeData().map(idOf);
|
||||
if (hideEdge === 'all') this.hiddenEdges = graph.getEdgeData().map(idOf);
|
||||
else {
|
||||
this.hiddenEdges = Array.from(
|
||||
new Set(this.target.map((id) => graph.getRelatedEdgesData(id, hideEdges).map(idOf)).flat()),
|
||||
new Set(this.target.map((id) => graph.getRelatedEdgesData(id, hideEdge).map(idOf)).flat()),
|
||||
);
|
||||
}
|
||||
graph.hideElement(this.hiddenEdges);
|
||||
@ -286,7 +278,7 @@ export class DragElement extends BaseBehavior<DragElementOptions> {
|
||||
private unbindEvents() {
|
||||
const { graph } = this.context;
|
||||
|
||||
this.element.forEach((type) => {
|
||||
this.enableElements.forEach((type) => {
|
||||
graph.off(`${type}:${CommonEvent.DRAG_START}`, this.onDragStart);
|
||||
graph.off(`${type}:${CommonEvent.DRAG}`, this.onDrag);
|
||||
graph.off(`${type}:${CommonEvent.DRAG_END}`, this.onDragEnd);
|
||||
|
Loading…
Reference in New Issue
Block a user