feat: v5-quadratic (#4656)

* add: add a test demo

* feat: add quadratic

* add: add unit test demo

* fix: add seItemState(selected、active、highlight、inactive、disable) test into spec.
This commit is contained in:
MaLaiXiGua 2023-06-25 14:40:46 +08:00 committed by GitHub
parent 1a029724cf
commit 7405f26c76
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 1163 additions and 1 deletions

View File

@ -24,7 +24,7 @@ import RotateCanvas3D from './behavior/rotate-canvas-3d';
import TrackCanvas3D from './behavior/track-canvas-3d';
import OrbitCanvas3D from './behavior/orbit-canvas-3d';
import { HoverActivate } from './behavior/hover-activate';
import { Quadratic } from './item/edge';
const stdLib = {
transforms: {
comboFromNode,
@ -63,6 +63,7 @@ const stdLib = {
},
edges: {
'line-edge': LineEdge,
'quadratic-edge': Quadratic
},
combos: {},
};

View File

@ -1 +1,2 @@
export * from './line';
export * from './quadratic'

View File

@ -0,0 +1,119 @@
import { Point } from '../../../types/common';
import {
EdgeDisplayModel,
EdgeModelData,
EdgeShapeMap,
} from '../../../types/edge';
import { State } from '../../../types/item';
import { BaseEdge } from './base';
export class Quadratic extends BaseEdge {
public type = 'line-edge';
public defaultStyles = {
keyShape: {
controlPoints: [0, 0], //precise x-axis, y-axis coordinates of control points
curvePosition: 0, //control point coordinates described by percentage,range 0 to 1
curveOffset: [0, 0], //a point coordinate that quadratic curve to
stroke: '#000000',
isBillboard: true,
},
};
constructor(props) {
super(props);
// suggest to merge default styles like this to avoid style value missing
// this.defaultStyles = mergeStyles([this.baseDefaultStyles, this.defaultStyles]);
}
public draw(
model: EdgeDisplayModel,
sourcePoint: Point,
targetPoint: Point,
shapeMap: EdgeShapeMap,
diffData?: { previous: EdgeModelData; current: EdgeModelData },
diffState?: { previous: State[]; current: State[] },
): EdgeShapeMap {
const { data = {} } = model;
const shapes: EdgeShapeMap = { keyShape: undefined };
shapes.keyShape = this.drawKeyShape(
model,
sourcePoint,
targetPoint,
shapeMap,
diffData,
);
if (data.haloShape) {
shapes.haloShape = this.drawHaloShape(model, shapeMap, diffData);
}
if (data.labelShape) {
shapes.labelShape = this.drawLabelShape(model, shapeMap, diffData);
}
// labelBackgroundShape
if (data.labelBackgroundShape) {
shapes.labelBackgroundShape = this.drawLabelBackgroundShape(
model,
shapeMap,
diffData,
);
}
if (data.iconShape) {
shapes.iconShape = this.drawIconShape(model, shapeMap, diffData);
}
// TODO: other shapes
return shapes;
}
public drawKeyShape(
model: EdgeDisplayModel,
sourcePoint: Point,
targetPoint: Point,
shapeMap: EdgeShapeMap,
diffData?: { previous: EdgeModelData; current: EdgeModelData },
diffState?: { previous: State[]; current: State[] },
) {
const { keyShape: keyShapeStyle } = this.mergedStyles as any;
const controlPoint = this.getControlPoint(sourcePoint, targetPoint, keyShapeStyle.curvePosition, keyShapeStyle.controlPoints, keyShapeStyle.curveOffset);
return this.upsertShape(
'path',
'keyShape',
{
...keyShapeStyle,
path: [['M', sourcePoint.x, sourcePoint.y], ['Q', controlPoint.x, controlPoint.y, targetPoint.x, targetPoint.y]],
},
shapeMap,
model,
);
}
/**
* calculate the control point by curvePosition|controlPoints|curveOffset
* @param startPoint: source point position of edge
* @param endPoint target point position of edge
* @param percent the proportion of control points' in the segment, Range 0 to 1
* @param controlPoints the control point position
* @param offset the curveOffset
* @returns control points
*/
private getControlPoint: (startPoint: Point,
endPoint: Point,
percent: number,
controlPoints: number[],
offset: number[]
) => Point = (
startPoint: Point,
endPoint: Point,
percent = 0,
controlPoints,
offset,
) => ({
x: (1 - percent) * startPoint.x + percent * endPoint.x + controlPoints[0] + offset[0],
y: (1 - percent) * startPoint.y + percent * endPoint.y + controlPoints[1] + offset[1],
})
}

View File

@ -0,0 +1,91 @@
import G6 from '../../../src/index';
import { container, height, width } from '../../datasets/const';
export default () => {
const data = {
nodes: [
{
id: 1,
data: {
x: 100,
y: 100,
type: 'circle-node',
},
},
{
id: 2,
data: {
x: 200,
y: 100,
type: 'circle-node',
},
},
],
edges: [
{
id: 'edge1',
source: 1,
target: 2,
data: {
type: 'quadratic-edge'
}
}
]
};
const edge: ((data: any) => any) = (edgeInnerModel: any) => {
const { id, data } = edgeInnerModel
return {
id,
data: {
...data,
keyShape: {
controlPoints: [150, 100],
// curvePosition: 0.5,
curveOffset: [0, 20],
stroke: 'blue'
},
// iconShape: {
// // img: 'https://gw.alipayobjects.com/zos/basement_prod/012bcf4f-423b-4922-8c24-32a89f8c41ce.svg',
// text: 'label',
// fill: 'blue'
// },
labelShape: {
text: 'label',
position: 'middle',
fill: 'blue'
},
labelBackgroundShape: {
fill: 'white'
},
}
}
}
const graph = new G6.Graph({
container,
width,
height,
data,
type: 'graph',
modes: {
default: ['click-select', 'drag-canvas', 'zoom-canvas', 'drag-node'],
},
node: (nodeInnerModel: any) => {
const { id, data } = nodeInnerModel;
return {
id,
data: {
...data,
keyShape: {
r: 16
},
}
}
},
edge,
});
return graph;
}

View File

@ -17,6 +17,7 @@ import demoFor4 from './demo/demoFor4';
import bugReproduce from './demo/bugReproduce';
import rect from './demo/rect';
import visual from './visual/visual';
import quadratic from './demo/quadratic';
export {
behaviors_activateRelations,
layouts_circular,
@ -37,4 +38,5 @@ export {
bugReproduce,
rect,
visual,
quadratic
};

View File

@ -0,0 +1,948 @@
// @ts-nocheck
import { DisplayObject } from '@antv/g';
import { clone } from '@antv/util';
import G6, {
EdgeDisplayModel,
Graph,
IGraph,
NodeDisplayModel,
} from '../../src/index';
import { LineEdge } from '../../src/stdlib/item/edge';
import { CircleNode } from '../../src/stdlib/item/node';
import { NodeModelData, NodeShapeMap } from '../../src/types/node';
import { extend } from '../../src/util/extend';
import { upsertShape } from '../../src/util/shape';
const container = document.createElement('div');
const width = document.getElementById('container')?.clientWidth;
const height = document.getElementById('container')?.clientHeight;
document.querySelector('body').appendChild(container);
let graph: IGraph<any>;
const data = {
nodes: [
{
id: 1,
data: {
x: 100,
y: 100,
type: 'circle-node',
},
},
{
id: 2,
data: {
x: 200,
y: 100,
type: 'circle-node',
},
},
],
edges: [
{
id: 'edge1',
source: 1,
target: 2,
data: {
type: 'quadratic-edge'
}
}
]
};
const edge: ((data: any) => any) = (edgeInnerModel: any) => {
const { id, data } = edgeInnerModel
return {
id,
data: {
keyShape: {
controlPoints: [0, 0],
curvePosition: 0.5,
curveOffset: [10, 10],
stroke: 'blue'
},
labelShape: {
text: 'label',
fill: 'blue'
},
labelBackgroundShape: {
fill: 'white'
},
...data,
}
}
}
describe('edge item', () => {
it('new graph with two nodes and one edge', (done) => {
graph = new G6.Graph({
container,
width,
height,
data,
type: 'graph',
modes: {
default: ['click-select', 'drag-canvas', 'zoom-canvas', 'drag-node'],
},
node: (nodeInnerModel: any) => {
const { id, data } = nodeInnerModel;
return {
id,
data: {
...data,
keyShape: {
r: 16
},
}
}
},
edge,
});
graph.on('afterrender', () => {
const edgeItem = graph.itemController.itemMap['edge1'];
expect(edgeItem).not.toBe(undefined);
expect(edgeItem.shapeMap.labelShape.attributes.text).toBe('label');
expect(edgeItem.shapeMap.labelShape.attributes.fill).toBe('blue');
expect(edgeItem.shapeMap.labelBackgroundShape.attributes.fill).toBe('white');
done();
});
});
it('update edge label', (done) => {
const padding = [4, 16, 4, 8];
graph.updateData('edge', {
id: 'edge1',
data: {
labelShape: {
text: 'edge-label',
},
labelBackgroundShape: {
radius: 10,
padding,
fill: '#f00',
},
iconShape: {
text: 'A',
fill: '#f00',
},
},
});
const edgeItem = graph.itemController.itemMap['edge1'];
expect(edgeItem.shapeMap.labelShape).not.toBe(undefined);
expect(edgeItem.shapeMap.labelShape.attributes.text).toBe('edge-label');
const fill = edgeItem.shapeMap.labelShape.attributes.fill;
expect(fill).toBe('rgba(0,0,0,0.85)');
let labelBounds = edgeItem.shapeMap.labelShape.getGeometryBounds();
expect(edgeItem.shapeMap.labelBackgroundShape.attributes.width).toBe(
labelBounds.max[0] - labelBounds.min[0] + padding[1] + padding[3],
);
expect(edgeItem.shapeMap.labelBackgroundShape.attributes.height).toBe(
labelBounds.max[1] - labelBounds.min[1] + padding[0] + padding[2],
);
graph.updateData('edge', {
id: 'edge1',
data: {
labelShape: {
fill: '#00f',
position: 'start',
},
},
});
expect(edgeItem.shapeMap.labelShape.attributes.fill).toBe('#00f');
expect(
edgeItem.shapeMap.labelShape.attributes.x -
edgeItem.shapeMap.labelBackgroundShape.attributes.x,
).toBe(padding[3]);
labelBounds = edgeItem.shapeMap.labelShape.getGeometryBounds();
const labelWidth = labelBounds.max[0] - labelBounds.min[0];
const labelHeight = labelBounds.max[1] - labelBounds.min[1];
const labelBgBounds =
edgeItem.shapeMap.labelBackgroundShape.getGeometryBounds();
const labelBgWidth = labelBgBounds.max[0] - labelBgBounds.min[0];
const labelBgHeight = labelBgBounds.max[1] - labelBgBounds.min[1];
expect(labelBgWidth - labelWidth).toBe(padding[1] + padding[3]);
expect(labelBgHeight - labelHeight).toBe(padding[0] + padding[2]);
graph.updateData('edge', {
id: 'edge1',
data: {
labelShape: undefined,
},
});
expect(edgeItem.shapeMap.labelShape).toBe(undefined);
expect(edgeItem.shapeMap.labelBackgroundShape).toBe(undefined);
done();
});
it('update edge icon', (done) => {
// add image icon to follow the label at path's center
graph.updateData('edge', {
id: 'edge1',
data: {
labelShape: {
text: 'abcddd',
fill: '#f00',
position: 'center',
},
iconShape: {
text: '',
img: 'https://gw.alipayobjects.com/zos/basement_prod/012bcf4f-423b-4922-8c24-32a89f8c41ce.svg',
// text: 'A',
fill: '#f00',
fontSize: 20,
},
},
});
const edgeItem = graph.itemController.itemMap['edge1'];
let { labelShape, iconShape, labelBackgroundShape } = edgeItem.shapeMap;
expect(iconShape.attributes.x + iconShape.attributes.width + 6).toBe(
labelBackgroundShape.getGeometryBounds().min[0] +
labelBackgroundShape.attributes.x,
);
expect(iconShape.attributes.transform).toBe(
labelBackgroundShape.attributes.transform,
);
expect(
Math.floor(iconShape.attributes.y + iconShape.attributes.height / 2),
).toBeCloseTo(
Math.floor(
labelBackgroundShape.getGeometryBounds().center[1] +
labelBackgroundShape.attributes.y,
),
0.01,
);
// update icon to be a text
graph.updateData('edge', {
id: 'edge1',
data: {
iconShape: {
text: 'A',
fill: '#f00',
fontWeight: 800,
},
},
});
labelShape = edgeItem.shapeMap['labelShape'];
iconShape = edgeItem.shapeMap['iconShape'];
labelBackgroundShape = edgeItem.shapeMap['labelBackgroundShape'];
expect(iconShape.attributes.x + iconShape.attributes.fontSize + 6).toBe(
labelBackgroundShape.getGeometryBounds().min[0] +
labelBackgroundShape.attributes.x,
);
expect(iconShape.attributes.transform).toBe(
labelBackgroundShape.attributes.transform,
);
expect(
Math.floor(iconShape.attributes.y + iconShape.attributes.fontSize / 2),
).toBeCloseTo(
Math.floor(
labelBackgroundShape.getGeometryBounds().center[1] +
labelBackgroundShape.attributes.y,
),
0.01,
);
// move label to the start, and the icon follows
graph.updateData('edge', {
id: 'edge1',
data: {
labelShape: {
position: 'start',
},
},
});
labelShape = edgeItem.shapeMap['labelShape'];
iconShape = edgeItem.shapeMap['iconShape'];
labelBackgroundShape = edgeItem.shapeMap['labelBackgroundShape'];
expect(iconShape.attributes.x + iconShape.attributes.fontSize + 6).toBe(
labelBackgroundShape.getGeometryBounds().min[0] +
labelBackgroundShape.attributes.x,
);
expect(iconShape.attributes.transform).toBe(
labelShape.attributes.transform,
);
expect(iconShape.attributes.y + iconShape.attributes.fontSize / 2).toBe(
labelBackgroundShape.getGeometryBounds().center[1] +
labelBackgroundShape.attributes.y,
);
graph.destroy();
done();
});
});
describe('state', () => {
it('edge state selected', (done) => {
const graph = new Graph({
container,
width: 500,
height: 500,
type: 'graph',
data: {
nodes: [
{
id: 'node1',
data: { x: 100, y: 200 },
},
{
id: 'node2',
data: { x: 100, y: 300 },
},
{
id: 'node3',
data: { x: 200, y: 300 },
},
],
edges: [
{
id: 'edge1',
source: 'node1',
target: 'node2',
data: {},
},
{
id: 'edge2',
source: 'node1',
target: 'node3',
data: {},
},
],
},
edgeState: {
selected: {
keyShape: {
stroke: '#0f0',
lineWidth: 2,
},
},
highlight: {
keyShape: {
stroke: '#00f',
opacity: 0.5,
},
},
},
});
graph.on('afterrender', () => {
expect(graph.findIdByState('edge', 'selected').length).toBe(0);
graph.setItemState('edge1', 'selected', true);
expect(graph.findIdByState('edge', 'selected').length).toBe(1);
expect(graph.findIdByState('edge', 'selected')[0]).toBe('edge1');
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.stroke,
).toBe('#0f0');
graph.setItemState('edge1', 'selected', false);
expect(graph.findIdByState('edge', 'selected').length).toBe(0);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(1);
// set multiple edges state
graph.setItemState(['edge1', 'edge2'], 'selected', true);
expect(graph.findIdByState('edge', 'selected').length).toBe(2);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.stroke,
).toBe('#0f0');
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.stroke,
).toBe('#0f0');
graph.setItemState('edge1', 'selected', false);
expect(graph.findIdByState('edge', 'selected').length).toBe(1);
expect(graph.findIdByState('edge', 'selected')[0]).toBe('edge2');
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(1);
graph.setItemState(['edge1', 'edge2'], 'selected', false);
expect(graph.findIdByState('edge', 'selected').length).toBe(0);
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.lineWidth,
).toBe(1);
graph.setItemState(['edge2', 'edge1'], ['selected', 'highlight'], true);
expect(graph.findIdByState('edge', 'selected').length).toBe(2);
expect(graph.findIdByState('edge', 'highlight').length).toBe(2);
// should be merged styles from selected and highlight
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.stroke,
).toBe('#00f');
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.opacity,
).toBe(0.5);
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.stroke,
).toBe('#00f');
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.opacity,
).toBe(0.5);
// clear states
graph.clearItemState(['edge1', 'edge2']);
expect(graph.findIdByState('edge', 'selected').length).toBe(0);
expect(graph.findIdByState('edge', 'highlight').length).toBe(0);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(1);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.opacity,
).toBe(1);
graph.destroy();
done();
});
});
it('edge state active', (done) => {
const graph = new Graph({
container,
width: 500,
height: 500,
type: 'graph',
data: {
nodes: [
{
id: 'node1',
data: { x: 100, y: 200 },
},
{
id: 'node2',
data: { x: 100, y: 300 },
},
{
id: 'node3',
data: { x: 200, y: 300 },
},
],
edges: [
{
id: 'edge1',
source: 'node1',
target: 'node2',
data: {},
},
{
id: 'edge2',
source: 'node1',
target: 'node3',
data: {},
},
],
},
edgeState: {
active: {
keyShape: {
stroke: '#0f0',
lineWidth: 2,
},
},
highlight: {
keyShape: {
stroke: '#00f',
opacity: 0.5,
},
},
},
});
graph.on('afterrender', () => {
expect(graph.findIdByState('edge', 'active').length).toBe(0);
graph.setItemState('edge1', 'active', true);
expect(graph.findIdByState('edge', 'active').length).toBe(1);
expect(graph.findIdByState('edge', 'active')[0]).toBe('edge1');
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.stroke,
).toBe('#0f0');
graph.setItemState('edge1', 'active', false);
expect(graph.findIdByState('edge', 'active').length).toBe(0);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(1);
// set multiple edges state
graph.setItemState(['edge1', 'edge2'], 'active', true);
expect(graph.findIdByState('edge', 'active').length).toBe(2);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.stroke,
).toBe('#0f0');
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.stroke,
).toBe('#0f0');
graph.setItemState('edge1', 'active', false);
expect(graph.findIdByState('edge', 'active').length).toBe(1);
expect(graph.findIdByState('edge', 'active')[0]).toBe('edge2');
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(1);
graph.setItemState(['edge1', 'edge2'], 'active', false);
expect(graph.findIdByState('edge', 'active').length).toBe(0);
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.lineWidth,
).toBe(1);
graph.setItemState(['edge2', 'edge1'], ['active', 'highlight'], true);
expect(graph.findIdByState('edge', 'active').length).toBe(2);
expect(graph.findIdByState('edge', 'highlight').length).toBe(2);
// should be merged styles from active and highlight
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.stroke,
).toBe('#00f');
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.opacity,
).toBe(0.5);
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.stroke,
).toBe('#00f');
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.opacity,
).toBe(0.5);
// clear states
graph.clearItemState(['edge1', 'edge2']);
expect(graph.findIdByState('edge', 'active').length).toBe(0);
expect(graph.findIdByState('edge', 'highlight').length).toBe(0);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(1);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.opacity,
).toBe(1);
graph.destroy();
done();
});
});
it('edge state highlight', (done) => {
const graph = new Graph({
container,
width: 500,
height: 500,
type: 'graph',
data: {
nodes: [
{
id: 'node1',
data: { x: 100, y: 200 },
},
{
id: 'node2',
data: { x: 100, y: 300 },
},
{
id: 'node3',
data: { x: 200, y: 300 },
},
],
edges: [
{
id: 'edge1',
source: 'node1',
target: 'node2',
data: {},
},
{
id: 'edge2',
source: 'node1',
target: 'node3',
data: {},
},
],
},
edgeState: {
highlight: {
keyShape: {
stroke: '#0f0',
lineWidth: 2,
},
},
highlight: {
keyShape: {
stroke: '#00f',
opacity: 0.5,
},
},
},
});
graph.on('afterrender', () => {
expect(graph.findIdByState('edge', 'highlight').length).toBe(0);
graph.setItemState('edge1', 'highlight', true);
expect(graph.findIdByState('edge', 'highlight').length).toBe(1);
expect(graph.findIdByState('edge', 'highlight')[0]).toBe('edge1');
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.stroke,
).toBe('#00f');
graph.setItemState('edge1', 'highlight', false);
expect(graph.findIdByState('edge', 'highlight').length).toBe(0);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(1);
// set multiple edges state
graph.setItemState(['edge1', 'edge2'], 'highlight', true);
expect(graph.findIdByState('edge', 'highlight').length).toBe(2);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.stroke,
).toBe('#00f');
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.stroke,
).toBe('#00f');
graph.setItemState('edge1', 'highlight', false);
expect(graph.findIdByState('edge', 'highlight').length).toBe(1);
expect(graph.findIdByState('edge', 'highlight')[0]).toBe('edge2');
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(1);
graph.setItemState(['edge1', 'edge2'], 'highlight', false);
expect(graph.findIdByState('edge', 'highlight').length).toBe(0);
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.lineWidth,
).toBe(1);
graph.setItemState(['edge2', 'edge1'], ['highlight', 'highlight'], true);
expect(graph.findIdByState('edge', 'highlight').length).toBe(2);
expect(graph.findIdByState('edge', 'highlight').length).toBe(2);
// should be merged styles from highlight and highlight
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.stroke,
).toBe('#00f');
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.opacity,
).toBe(0.5);
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.stroke,
).toBe('#00f');
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.opacity,
).toBe(0.5);
// clear states
graph.clearItemState(['edge1', 'edge2']);
expect(graph.findIdByState('edge', 'highlight').length).toBe(0);
expect(graph.findIdByState('edge', 'highlight').length).toBe(0);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(1);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.opacity,
).toBe(1);
graph.destroy();
done();
});
});
it('edge state inactive', (done) => {
const graph = new Graph({
container,
width: 500,
height: 500,
type: 'graph',
data: {
nodes: [
{
id: 'node1',
data: { x: 100, y: 200 },
},
{
id: 'node2',
data: { x: 100, y: 300 },
},
{
id: 'node3',
data: { x: 200, y: 300 },
},
],
edges: [
{
id: 'edge1',
source: 'node1',
target: 'node2',
data: {},
},
{
id: 'edge2',
source: 'node1',
target: 'node3',
data: {},
},
],
},
edgeState: {
inactive: {
keyShape: {
stroke: '#0f0',
lineWidth: 2,
},
},
highlight: {
keyShape: {
stroke: '#00f',
opacity: 0.5,
},
},
},
});
graph.on('afterrender', () => {
expect(graph.findIdByState('edge', 'inactive').length).toBe(0);
graph.setItemState('edge1', 'inactive', true);
expect(graph.findIdByState('edge', 'inactive').length).toBe(1);
expect(graph.findIdByState('edge', 'inactive')[0]).toBe('edge1');
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.stroke,
).toBe('#0f0');
graph.setItemState('edge1', 'inactive', false);
expect(graph.findIdByState('edge', 'inactive').length).toBe(0);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(1);
// set multiple edges state
graph.setItemState(['edge1', 'edge2'], 'inactive', true);
expect(graph.findIdByState('edge', 'inactive').length).toBe(2);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.stroke,
).toBe('#0f0');
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.stroke,
).toBe('#0f0');
graph.setItemState('edge1', 'inactive', false);
expect(graph.findIdByState('edge', 'inactive').length).toBe(1);
expect(graph.findIdByState('edge', 'inactive')[0]).toBe('edge2');
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(1);
graph.setItemState(['edge1', 'edge2'], 'inactive', false);
expect(graph.findIdByState('edge', 'inactive').length).toBe(0);
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.lineWidth,
).toBe(1);
graph.setItemState(['edge2', 'edge1'], ['inactive', 'highlight'], true);
expect(graph.findIdByState('edge', 'inactive').length).toBe(2);
expect(graph.findIdByState('edge', 'highlight').length).toBe(2);
// should be merged styles from inactive and highlight
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.stroke,
).toBe('#00f');
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.opacity,
).toBe(0.5);
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.stroke,
).toBe('#00f');
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.opacity,
).toBe(0.5);
// clear states
graph.clearItemState(['edge1', 'edge2']);
expect(graph.findIdByState('edge', 'inactive').length).toBe(0);
expect(graph.findIdByState('edge', 'highlight').length).toBe(0);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(1);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.opacity,
).toBe(1);
graph.destroy();
done();
});
});
it('edge state disable', (done) => {
const graph = new Graph({
container,
width: 500,
height: 500,
type: 'graph',
data: {
nodes: [
{
id: 'node1',
data: { x: 100, y: 200 },
},
{
id: 'node2',
data: { x: 100, y: 300 },
},
{
id: 'node3',
data: { x: 200, y: 300 },
},
],
edges: [
{
id: 'edge1',
source: 'node1',
target: 'node2',
data: {},
},
{
id: 'edge2',
source: 'node1',
target: 'node3',
data: {},
},
],
},
edgeState: {
disable: {
keyShape: {
stroke: '#0f0',
lineWidth: 2,
},
},
highlight: {
keyShape: {
stroke: '#00f',
opacity: 0.5,
},
},
},
});
graph.on('afterrender', () => {
expect(graph.findIdByState('edge', 'disable').length).toBe(0);
graph.setItemState('edge1', 'disable', true);
expect(graph.findIdByState('edge', 'disable').length).toBe(1);
expect(graph.findIdByState('edge', 'disable')[0]).toBe('edge1');
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.stroke,
).toBe('#0f0');
graph.setItemState('edge1', 'disable', false);
expect(graph.findIdByState('edge', 'disable').length).toBe(0);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(1);
// set multiple edges state
graph.setItemState(['edge1', 'edge2'], 'disable', true);
expect(graph.findIdByState('edge', 'disable').length).toBe(2);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.stroke,
).toBe('#0f0');
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.stroke,
).toBe('#0f0');
graph.setItemState('edge1', 'disable', false);
expect(graph.findIdByState('edge', 'disable').length).toBe(1);
expect(graph.findIdByState('edge', 'disable')[0]).toBe('edge2');
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(1);
graph.setItemState(['edge1', 'edge2'], 'disable', false);
expect(graph.findIdByState('edge', 'disable').length).toBe(0);
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.lineWidth,
).toBe(1);
graph.setItemState(['edge2', 'edge1'], ['disable', 'highlight'], true);
expect(graph.findIdByState('edge', 'disable').length).toBe(2);
expect(graph.findIdByState('edge', 'highlight').length).toBe(2);
// should be merged styles from disable and highlight
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.stroke,
).toBe('#00f');
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.opacity,
).toBe(0.5);
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.lineWidth,
).toBe(2);
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.stroke,
).toBe('#00f');
expect(
graph.itemController.itemMap['edge2'].shapeMap.keyShape.style.opacity,
).toBe(0.5);
// clear states
graph.clearItemState(['edge1', 'edge2']);
expect(graph.findIdByState('edge', 'disable').length).toBe(0);
expect(graph.findIdByState('edge', 'highlight').length).toBe(0);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.lineWidth,
).toBe(1);
expect(
graph.itemController.itemMap['edge1'].shapeMap.keyShape.style.opacity,
).toBe(1);
graph.destroy();
done();
});
});
});