mirror of
https://gitee.com/antv/g6.git
synced 2024-12-02 19:58:46 +08:00
fix: keyshape states bug & add tree demo
This commit is contained in:
parent
c6c8f9cc5e
commit
755008f04b
332
examples/tree/customItemTree/demo/customEdgeTree.js
Normal file
332
examples/tree/customItemTree/demo/customEdgeTree.js
Normal file
@ -0,0 +1,332 @@
|
||||
import G6 from '@antv/g6';
|
||||
|
||||
const COLLAPSE_ICON = function COLLAPSE_ICON(x, y, r) {
|
||||
return [
|
||||
['M', x - r, y - r],
|
||||
['a', r, r, 0, 1, 0, r * 2, 0],
|
||||
['a', r, r, 0, 1, 0, -r * 2, 0],
|
||||
['M', x + 2 - r, y - r],
|
||||
['L', x + r - 2, y - r],
|
||||
];
|
||||
};
|
||||
const EXPAND_ICON = function EXPAND_ICON(x, y, r) {
|
||||
return [
|
||||
['M', x - r, y - r],
|
||||
['a', r, r, 0, 1, 0, r * 2, 0],
|
||||
['a', r, r, 0, 1, 0, -r * 2, 0],
|
||||
['M', x + 2 - r, y - r],
|
||||
['L', x + r - 2, y - r],
|
||||
['M', x, y - 2 * r + 2],
|
||||
['L', x, y - 2],
|
||||
];
|
||||
};
|
||||
|
||||
const data = {
|
||||
id: 'root',
|
||||
label: 'root',
|
||||
children: [
|
||||
{
|
||||
id: 'c1',
|
||||
label: 'c1',
|
||||
children: [
|
||||
{
|
||||
id: 'c1-1',
|
||||
label: 'c1-1',
|
||||
},
|
||||
{
|
||||
id: 'c1-2',
|
||||
label: 'c1-2',
|
||||
children: [
|
||||
{
|
||||
id: 'c1-2-1',
|
||||
label: 'c1-2-1'
|
||||
},
|
||||
{
|
||||
id: 'c1-2-2',
|
||||
label: 'c1-2-2'
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'c2',
|
||||
label: 'c2'
|
||||
},
|
||||
{
|
||||
id: 'c3',
|
||||
label: 'c3',
|
||||
children: [
|
||||
{
|
||||
id: 'c3-1',
|
||||
label: 'c3-1'
|
||||
},
|
||||
{
|
||||
id: 'c3-2',
|
||||
label: 'c3-2',
|
||||
children: [
|
||||
{
|
||||
id: 'c3-2-1',
|
||||
label: 'c3-2-1'
|
||||
},
|
||||
{
|
||||
id: 'c3-2-2',
|
||||
label: 'c3-2-2'
|
||||
},
|
||||
{
|
||||
id: 'c3-2-3',
|
||||
label: 'c3-2-3'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'c3-3',
|
||||
label: 'c3-3'
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
G6.Util.traverseTree(data, d => {
|
||||
d.leftIcon = {
|
||||
style: {
|
||||
fill: '#e6fffb',
|
||||
stroke: '#e6fffb'
|
||||
},
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*Q_FQT6nwEC8AAAAAAAAAAABkARQnAQ'
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
G6.registerNode('icon-node', {
|
||||
options: {
|
||||
size: [60, 20],
|
||||
stroke: '#91d5ff',
|
||||
fill: '#91d5ff'
|
||||
},
|
||||
draw(cfg, group) {
|
||||
const styles = this.getShapeStyle(cfg)
|
||||
const { labelCfg = {} } = cfg
|
||||
|
||||
const keyShape = group.addShape('rect', {
|
||||
attrs: {
|
||||
...styles,
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* leftIcon 格式如下:
|
||||
* {
|
||||
* style: ShapeStyle;
|
||||
* img: ''
|
||||
* }
|
||||
*/
|
||||
if (cfg.leftIcon) {
|
||||
const { style, img } = cfg.leftIcon
|
||||
group.addShape('rect', {
|
||||
attrs: {
|
||||
x: 1,
|
||||
y: 1,
|
||||
width: 38,
|
||||
height: styles.height - 2,
|
||||
fill: '#8c8c8c',
|
||||
...style
|
||||
}
|
||||
})
|
||||
|
||||
group.addShape('image', {
|
||||
attrs: {
|
||||
x: 8,
|
||||
y: 8,
|
||||
width: 24,
|
||||
height: 24,
|
||||
img: img || 'https://g.alicdn.com/cm-design/arms-trace/1.0.155/styles/armsTrace/images/TAIR.png',
|
||||
},
|
||||
name: 'image-shape',
|
||||
});
|
||||
}
|
||||
|
||||
// 如果不需要动态增加或删除元素,则不需要 add 这两个 marker
|
||||
group.addShape('marker', {
|
||||
attrs: {
|
||||
x: 40,
|
||||
y: 52,
|
||||
r: 6,
|
||||
stroke: '#73d13d',
|
||||
cursor: 'pointer',
|
||||
symbol: EXPAND_ICON
|
||||
},
|
||||
name: 'add-item'
|
||||
})
|
||||
|
||||
group.addShape('marker', {
|
||||
attrs: {
|
||||
x: 80,
|
||||
y: 52,
|
||||
r: 6,
|
||||
stroke: '#ff4d4f',
|
||||
cursor: 'pointer',
|
||||
symbol: COLLAPSE_ICON
|
||||
},
|
||||
name: 'remove-item'
|
||||
})
|
||||
|
||||
if (cfg.label) {
|
||||
group.addShape('text', {
|
||||
attrs: {
|
||||
...labelCfg.style,
|
||||
text: cfg.label,
|
||||
x: 50,
|
||||
y: 25,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return keyShape
|
||||
}
|
||||
}, 'rect')
|
||||
|
||||
G6.registerEdge('flow-line', {
|
||||
draw(cfg, group) {
|
||||
const startPoint = cfg.startPoint;
|
||||
const endPoint = cfg.endPoint;
|
||||
|
||||
const { style } = cfg
|
||||
const shape = group.addShape('path', {
|
||||
attrs: {
|
||||
stroke: style.stroke,
|
||||
endArrow: style.endArrow,
|
||||
path: [
|
||||
['M', startPoint.x, startPoint.y],
|
||||
['L', startPoint.x, (startPoint.y + endPoint.y) / 2],
|
||||
['L', endPoint.x, (startPoint.y + endPoint.y) / 2,],
|
||||
['L', endPoint.x, endPoint.y],
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
return shape;
|
||||
}
|
||||
});
|
||||
|
||||
const defaultStateStyles = {
|
||||
hover: {
|
||||
stroke: '#1890ff',
|
||||
lineWidth: 2
|
||||
}
|
||||
}
|
||||
|
||||
const defaultNodeStyle = {
|
||||
fill: '#91d5ff',
|
||||
stroke: '#40a9ff',
|
||||
radius: 5
|
||||
}
|
||||
|
||||
const defaultEdgeStyle = {
|
||||
stroke: '#91d5ff',
|
||||
endArrow: {
|
||||
path: 'M 0,0 L 12, 6 L 9,0 L 12, -6 Z',
|
||||
fill: '#91d5ff',
|
||||
d: -20
|
||||
}
|
||||
}
|
||||
|
||||
const defaultLayout = {
|
||||
type: 'compactBox',
|
||||
direction: 'TB',
|
||||
getId: function getId(d) {
|
||||
return d.id;
|
||||
},
|
||||
getHeight: function getHeight() {
|
||||
return 16;
|
||||
},
|
||||
getWidth: function getWidth() {
|
||||
return 16;
|
||||
},
|
||||
getVGap: function getVGap() {
|
||||
return 40;
|
||||
},
|
||||
getHGap: function getHGap() {
|
||||
return 70;
|
||||
},
|
||||
}
|
||||
|
||||
const defaultLabelCfg = {
|
||||
style: {
|
||||
fill: '#000',
|
||||
fontSize: 12
|
||||
}
|
||||
}
|
||||
|
||||
const width = document.getElementById('container').scrollWidth;
|
||||
const height = document.getElementById('container').scrollHeight || 500;
|
||||
|
||||
const minimap = new G6.Minimap({
|
||||
size: [150, 100]
|
||||
})
|
||||
const graph = new G6.TreeGraph({
|
||||
container: 'container',
|
||||
width,
|
||||
height,
|
||||
linkCenter: true,
|
||||
plugins: [minimap],
|
||||
modes: {
|
||||
default: [
|
||||
'drag-canvas',
|
||||
'zoom-canvas',
|
||||
],
|
||||
},
|
||||
defaultNode: {
|
||||
type: 'icon-node',
|
||||
size: [120, 40],
|
||||
style: defaultNodeStyle,
|
||||
labelCfg: defaultLabelCfg
|
||||
},
|
||||
defaultEdge: {
|
||||
type: 'flow-line',
|
||||
style: defaultEdgeStyle,
|
||||
},
|
||||
nodeStateStyles: defaultStateStyles,
|
||||
edgeStateStyles: defaultStateStyles,
|
||||
layout: defaultLayout
|
||||
});
|
||||
|
||||
graph.data(data);
|
||||
graph.render();
|
||||
graph.fitView();
|
||||
|
||||
graph.on('node:mouseenter', evt => {
|
||||
const { item } = evt
|
||||
graph.setItemState(item, 'hover', true)
|
||||
})
|
||||
|
||||
graph.on('node:mouseleave', evt => {
|
||||
const { item } = evt
|
||||
graph.setItemState(item, 'hover', false)
|
||||
})
|
||||
|
||||
graph.on('node:click', evt => {
|
||||
const { item, target } = evt
|
||||
const targetType = target.get('type')
|
||||
const name = target.get('name')
|
||||
|
||||
// 增加元素
|
||||
if (targetType === 'marker') {
|
||||
const model = item.getModel()
|
||||
if (name === 'add-item') {
|
||||
if (!model.children) {
|
||||
model.children = []
|
||||
}
|
||||
model.children.push({
|
||||
id: Math.random(),
|
||||
label: Math.random()
|
||||
})
|
||||
graph.updateChild(model, model.id)
|
||||
} else if (name === 'remove-item') {
|
||||
graph.removeChild(model.id)
|
||||
}
|
||||
}
|
||||
})
|
@ -4,6 +4,14 @@
|
||||
"en": "Category"
|
||||
},
|
||||
"demos": [
|
||||
{
|
||||
"filename": "customEdgeTree.js",
|
||||
"title": {
|
||||
"zh": "自定义树图中的边",
|
||||
"en": "Edges on Tree"
|
||||
},
|
||||
"screenshot": "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*AncCQ5e7XncAAAAAAAAAAABkARQnAQ"
|
||||
},
|
||||
{
|
||||
"filename": "treeEdgeLabel.js",
|
||||
"title": {
|
||||
|
@ -9,5 +9,6 @@ Thanks to the item's custom mechanism of G6, users can design their own tree wit
|
||||
|
||||
Combining with custom items, the complex tree visualization can be realized.
|
||||
|
||||
- Examples 1 : Add labels for edges.
|
||||
- Examples 2 : Customize the node with expand and collapse button.
|
||||
- Examples 1 : Customize the node and the edge with tree graph, support add or remove node.
|
||||
- Examples 2 : Add labels for edges.
|
||||
- Examples 3 : Customize the node with expand and collapse button.
|
||||
|
@ -9,5 +9,6 @@ G6 自定义节点与边机制允许用户对树图视觉样式进行定制。
|
||||
|
||||
通过结合自定义元素,可以实现较为复杂的树可视化。
|
||||
|
||||
- 代码演示 1 :为边增加文本标签。
|
||||
- 代码演示 2 :自定义带有收缩/扩展按钮的节点。
|
||||
- 代码演示 1: 自定义树图中的节点及边,支持增加和删除节点;
|
||||
- 代码演示 2 :为边增加文本标签。
|
||||
- 代码演示 3 :自定义带有收缩/扩展按钮的节点。
|
||||
|
@ -50,7 +50,7 @@
|
||||
"site:deploy": "npm run site:build && gh-pages -d public",
|
||||
"start": "npm run site:develop",
|
||||
"test": "jest",
|
||||
"test-live": "DEBUG_MODE=1 jest --watch ./tests/unit/combo-issue-spec.ts",
|
||||
"test-live": "DEBUG_MODE=1 jest --watch ./tests/unit/issues-spec.ts",
|
||||
"lint-staged:js": "eslint --ext .js,.jsx,.ts,.tsx",
|
||||
"watch": "father build -w",
|
||||
"cdn": "antv-bin upload -n @antv/g6"
|
||||
|
@ -374,6 +374,7 @@ export const shapeBase: ShapeOptions = {
|
||||
mix(originStyle[keyShapeName], {
|
||||
[key]: enableStyle,
|
||||
});
|
||||
delete originStyle[key]
|
||||
}
|
||||
delete enableStatesStyle[key];
|
||||
}
|
||||
|
@ -271,7 +271,7 @@ export interface GraphOptions {
|
||||
linkCenter?: boolean;
|
||||
}
|
||||
|
||||
interface StateStyles {
|
||||
export interface StateStyles {
|
||||
[key: string]: ShapeStyle | {
|
||||
[key: string]: ShapeStyle
|
||||
}
|
||||
|
@ -175,7 +175,7 @@ const DagreLayout = () => {
|
||||
|
||||
graph.on('canvas:click', e => {
|
||||
console.log(graph.toDataURL('image/jpeg', '#fff'));
|
||||
// graph.downloadImage('test', '#eee');
|
||||
graph.downloadImage('test', 'image/png');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
441
stories/Tree/component/flow-component.tsx
Normal file
441
stories/Tree/component/flow-component.tsx
Normal file
@ -0,0 +1,441 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import G6 from '../../../src';
|
||||
import { traverseTree } from '../../../src/util/graphic'
|
||||
import { IGraph, ITreeGraph } from '../../../src/interface/graph';
|
||||
import { EdgeConfig, TreeGraphData, StateStyles, ShapeStyle } from '../../../src/types';
|
||||
import { INode, IEdge } from '../../../src/interface/item';
|
||||
|
||||
interface IFlowCharts {
|
||||
data: TreeGraphData;
|
||||
width?: number;
|
||||
height?: number;
|
||||
nodeType?: string;
|
||||
edgeType?: string;
|
||||
nodeStyle?: ShapeStyle;
|
||||
edgeStyle?: ShapeStyle;
|
||||
nodeStateStyles?: StateStyles;
|
||||
edgeStateStyles?: StateStyles;
|
||||
nodeSize?: number | number[];
|
||||
labelCfg?: {
|
||||
style: {
|
||||
stroke?: string;
|
||||
fontSize?: number;
|
||||
}
|
||||
};
|
||||
layout?: any;
|
||||
enableEdit?: boolean;
|
||||
handleNodeClick?: (item: INode, graph: IGraph) => void;
|
||||
handleEdgeClick?: (item: IEdge, graph: IGraph) => void;
|
||||
handleNodeHover?: (item: INode, graph: IGraph) => void;
|
||||
handleNodeUnHover?: (item: INode, graph: IGraph) => void;
|
||||
handleEdgeHover?: (item: INode, graph: IGraph) => void;
|
||||
handleEdgeUnHover?: (item: INode, graph: IGraph) => void;
|
||||
collapseExpand?: boolean;
|
||||
}
|
||||
|
||||
const COLLAPSE_ICON = function COLLAPSE_ICON(x, y, r) {
|
||||
return [
|
||||
['M', x - r, y - r],
|
||||
['a', r, r, 0, 1, 0, r * 2, 0],
|
||||
['a', r, r, 0, 1, 0, -r * 2, 0],
|
||||
['M', x + 2 - r, y - r],
|
||||
['L', x + r - 2, y - r],
|
||||
];
|
||||
};
|
||||
const EXPAND_ICON = function EXPAND_ICON(x, y, r) {
|
||||
return [
|
||||
['M', x - r, y - r],
|
||||
['a', r, r, 0, 1, 0, r * 2, 0],
|
||||
['a', r, r, 0, 1, 0, -r * 2, 0],
|
||||
['M', x + 2 - r, y - r],
|
||||
['L', x + r - 2, y - r],
|
||||
['M', x, y - 2 * r + 2],
|
||||
['L', x, y - 2],
|
||||
];
|
||||
};
|
||||
|
||||
const data1 = {
|
||||
id: 'root',
|
||||
label: 'root',
|
||||
children: [
|
||||
{
|
||||
id: 'c1',
|
||||
label: 'c1',
|
||||
children: [
|
||||
{
|
||||
id: 'c1-1',
|
||||
label: 'c1-1',
|
||||
},
|
||||
{
|
||||
id: 'c1-2',
|
||||
label: 'c1-2',
|
||||
children: [
|
||||
{
|
||||
id: 'c1-2-1',
|
||||
label: 'c1-2-1'
|
||||
},
|
||||
{
|
||||
id: 'c1-2-2',
|
||||
label: 'c1-2-2'
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'c2',
|
||||
label: 'c2'
|
||||
},
|
||||
{
|
||||
id: 'c3',
|
||||
label: 'c3',
|
||||
children: [
|
||||
{
|
||||
id: 'c3-1',
|
||||
label: 'c3-1'
|
||||
},
|
||||
{
|
||||
id: 'c3-2',
|
||||
label: 'c3-2',
|
||||
children: [
|
||||
{
|
||||
id: 'c3-2-1',
|
||||
label: 'c3-2-1'
|
||||
},
|
||||
{
|
||||
id: 'c3-2-2',
|
||||
label: 'c3-2-2'
|
||||
},
|
||||
{
|
||||
id: 'c3-2-3',
|
||||
label: 'c3-2-3'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'c3-3',
|
||||
label: 'c3-3'
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
traverseTree((data1 as any), d => {
|
||||
d.leftIcon = {
|
||||
style: {
|
||||
fill: '#e6fffb',
|
||||
stroke: '#e6fffb'
|
||||
},
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*Q_FQT6nwEC8AAAAAAAAAAABkARQnAQ'
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
G6.registerEdge('flow-line', {
|
||||
draw(cfg: EdgeConfig, group) {
|
||||
const startPoint = cfg.startPoint;
|
||||
const endPoint = cfg.endPoint;
|
||||
|
||||
const { style } = cfg
|
||||
const shape = group.addShape('path', {
|
||||
attrs: {
|
||||
stroke: style.stroke,
|
||||
endArrow: style.endArrow,
|
||||
path: [
|
||||
['M', startPoint.x, startPoint.y],
|
||||
['L', startPoint.x, (startPoint.y + endPoint.y) / 2],
|
||||
['L', endPoint.x, (startPoint.y + endPoint.y) / 2,],
|
||||
['L', endPoint.x, endPoint.y],
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
return shape;
|
||||
}
|
||||
});
|
||||
|
||||
let graph: ITreeGraph = null;
|
||||
|
||||
const defaultStateStyles = {
|
||||
hover: {
|
||||
stroke: '#1890ff',
|
||||
lineWidth: 2
|
||||
}
|
||||
}
|
||||
|
||||
const defaultNodeStyle = {
|
||||
fill: '#91d5ff',
|
||||
stroke: '#40a9ff',
|
||||
radius: 5
|
||||
}
|
||||
|
||||
const defaultEdgeStyle = {
|
||||
stroke: '#91d5ff',
|
||||
endArrow: {
|
||||
path: 'M 0,0 L 12, 6 L 9,0 L 12, -6 Z',
|
||||
fill: '#91d5ff',
|
||||
d: -20
|
||||
}
|
||||
}
|
||||
|
||||
const defaultLayout = {
|
||||
type: 'compactBox',
|
||||
direction: 'TB',
|
||||
getId: function getId(d) {
|
||||
return d.id;
|
||||
},
|
||||
getHeight: function getHeight() {
|
||||
return 16;
|
||||
},
|
||||
getWidth: function getWidth() {
|
||||
return 16;
|
||||
},
|
||||
getVGap: function getVGap() {
|
||||
return 40;
|
||||
},
|
||||
getHGap: function getHGap() {
|
||||
return 70;
|
||||
},
|
||||
}
|
||||
|
||||
const defaultLabelCfg = {
|
||||
style: {
|
||||
fill: '#000',
|
||||
fontSize: 12
|
||||
}
|
||||
}
|
||||
|
||||
const FlowTree: React.SFC<IFlowCharts> = ({
|
||||
data = data1,
|
||||
width = 500,
|
||||
height = 500,
|
||||
nodeType = 'icon-node',
|
||||
edgeType = 'flow-line',
|
||||
collapseExpand = false,
|
||||
nodeSize = [120, 40],
|
||||
labelCfg = defaultLabelCfg,
|
||||
layout = defaultLayout,
|
||||
enableEdit = true,
|
||||
nodeStyle = defaultNodeStyle,
|
||||
edgeStyle = defaultEdgeStyle,
|
||||
nodeStateStyles = defaultStateStyles,
|
||||
edgeStateStyles = defaultStateStyles,
|
||||
handleNodeClick,
|
||||
handleEdgeClick,
|
||||
handleNodeHover,
|
||||
handleNodeUnHover,
|
||||
handleEdgeHover,
|
||||
handleEdgeUnHover
|
||||
}) => {
|
||||
const container = React.useRef();
|
||||
|
||||
useEffect(() => {
|
||||
G6.registerNode('icon-node', {
|
||||
options: {
|
||||
size: [60, 20],
|
||||
stroke: '#91d5ff',
|
||||
fill: '#91d5ff'
|
||||
},
|
||||
draw(cfg, group) {
|
||||
const styles = this.getShapeStyle(cfg)
|
||||
const { labelCfg = {} } = cfg
|
||||
|
||||
const keyShape = group.addShape('rect', {
|
||||
attrs: {
|
||||
...styles,
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* leftIcon 格式如下:
|
||||
* {
|
||||
* style: ShapeStyle;
|
||||
* img: ''
|
||||
* }
|
||||
*/
|
||||
if (cfg.leftIcon) {
|
||||
const { style, img } = cfg.leftIcon as any
|
||||
group.addShape('rect', {
|
||||
attrs: {
|
||||
x: 1,
|
||||
y: 1,
|
||||
width: 38,
|
||||
height: styles.height - 2,
|
||||
fill: '#8c8c8c',
|
||||
...style
|
||||
}
|
||||
})
|
||||
|
||||
group.addShape('image', {
|
||||
attrs: {
|
||||
x: 8,
|
||||
y: 8,
|
||||
width: 24,
|
||||
height: 24,
|
||||
img: img || 'https://g.alicdn.com/cm-design/arms-trace/1.0.155/styles/armsTrace/images/TAIR.png',
|
||||
},
|
||||
name: 'image-shape',
|
||||
});
|
||||
}
|
||||
|
||||
if (enableEdit) {
|
||||
group.addShape('marker', {
|
||||
attrs: {
|
||||
x: 40,
|
||||
y: 52,
|
||||
r: 6,
|
||||
stroke: '#73d13d',
|
||||
cursor: 'pointer',
|
||||
symbol: EXPAND_ICON
|
||||
},
|
||||
name: 'add-item'
|
||||
})
|
||||
|
||||
group.addShape('marker', {
|
||||
attrs: {
|
||||
x: 80,
|
||||
y: 52,
|
||||
r: 6,
|
||||
stroke: '#ff4d4f',
|
||||
cursor: 'pointer',
|
||||
symbol: COLLAPSE_ICON
|
||||
},
|
||||
name: 'remove-item'
|
||||
})
|
||||
}
|
||||
|
||||
if (cfg.label) {
|
||||
group.addShape('text', {
|
||||
attrs: {
|
||||
...labelCfg.style,
|
||||
text: cfg.label,
|
||||
x: 50,
|
||||
y: 25,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return keyShape
|
||||
}
|
||||
}, 'rect')
|
||||
|
||||
if (!graph) {
|
||||
const minimap = new G6.Minimap({
|
||||
size: [150, 100]
|
||||
})
|
||||
graph = new G6.TreeGraph({
|
||||
container: container.current,
|
||||
width,
|
||||
height,
|
||||
linkCenter: true,
|
||||
plugins: [minimap],
|
||||
modes: {
|
||||
default: [
|
||||
'drag-canvas',
|
||||
'zoom-canvas',
|
||||
],
|
||||
},
|
||||
defaultNode: {
|
||||
type: nodeType,
|
||||
size: nodeSize,
|
||||
style: nodeStyle,
|
||||
labelCfg
|
||||
},
|
||||
defaultEdge: {
|
||||
type: edgeType,
|
||||
style: edgeStyle,
|
||||
},
|
||||
nodeStateStyles,
|
||||
edgeStateStyles,
|
||||
layout
|
||||
});
|
||||
|
||||
graph.data(data);
|
||||
graph.render();
|
||||
graph.fitView();
|
||||
|
||||
if (collapseExpand) {
|
||||
graph.addBehaviors({
|
||||
type: 'collapse-expand',
|
||||
onChange: function onChange(item, collapsed) {
|
||||
const data = item.get('model').data;
|
||||
data.collapsed = collapsed;
|
||||
return true;
|
||||
},
|
||||
}, 'default')
|
||||
}
|
||||
|
||||
graph.on('node:mouseenter', evt => {
|
||||
const { item } = evt
|
||||
graph.setItemState(item, 'hover', true)
|
||||
if (handleNodeHover) {
|
||||
handleNodeHover(item, graph)
|
||||
}
|
||||
})
|
||||
|
||||
graph.on('node:mouseleave', evt => {
|
||||
const { item } = evt
|
||||
graph.setItemState(item, 'hover', false)
|
||||
if (handleNodeUnHover) {
|
||||
handleNodeUnHover(item, graph)
|
||||
}
|
||||
})
|
||||
|
||||
graph.on('node:click', evt => {
|
||||
const { item, target } = evt
|
||||
const targetType = target.get('type')
|
||||
const name = target.get('name')
|
||||
|
||||
// 增加元素
|
||||
if (targetType === 'marker') {
|
||||
const model = item.getModel()
|
||||
if (name === 'add-item') {
|
||||
if (!model.children) {
|
||||
model.children = []
|
||||
}
|
||||
model.children.push({
|
||||
id: Math.random(),
|
||||
label: Math.random()
|
||||
})
|
||||
graph.updateChild(model, model.id)
|
||||
} else if (name === 'remove-item') {
|
||||
graph.removeChild(model.id)
|
||||
}
|
||||
} else {
|
||||
if (handleNodeClick) {
|
||||
handleNodeClick(item, graph)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
graph.on('edge:mouseenter', evt => {
|
||||
const { item } = evt
|
||||
graph.setItemState(item, 'hover', true)
|
||||
if (handleEdgeHover) {
|
||||
handleEdgeHover(item, graph)
|
||||
}
|
||||
})
|
||||
|
||||
graph.on('edge:mouseleave', evt => {
|
||||
const { item } = evt
|
||||
graph.setItemState(item, 'hover', false)
|
||||
if (handleEdgeUnHover) {
|
||||
handleEdgeUnHover(item, graph)
|
||||
}
|
||||
})
|
||||
|
||||
graph.on('edge:click', evt => {
|
||||
const { item } = evt
|
||||
if (handleEdgeClick) {
|
||||
handleEdgeClick(item, graph)
|
||||
}
|
||||
})
|
||||
}
|
||||
}, []);
|
||||
return <div ref={container}></div>;
|
||||
};
|
||||
|
||||
export default FlowTree;
|
@ -421,7 +421,7 @@ const FlowTree = () => {
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight,
|
||||
modes: {
|
||||
default: ['drag-canvas'],
|
||||
default: ['drag-canvas', 'drag-node'],
|
||||
},
|
||||
defaultNode: {
|
||||
shape: 'operation',
|
||||
|
@ -4,6 +4,7 @@ import React from 'react';
|
||||
import FlowTree from './component/flow-tree'
|
||||
import TreeData from './component/tree-data';
|
||||
import SlefTree from './component/self-tree'
|
||||
import FlowComponent from './component/flow-component'
|
||||
|
||||
export default { title: 'Tree' };
|
||||
|
||||
@ -11,3 +12,4 @@ storiesOf('Tree', module)
|
||||
.add('flow-tree', () => <FlowTree />)
|
||||
.add('tree-data', () => <TreeData />)
|
||||
.add('register flow tree', () => <SlefTree />)
|
||||
.add('FlowComponent', () => <FlowComponent />)
|
||||
|
@ -4,6 +4,101 @@ const div = document.createElement('div');
|
||||
div.id = 'container';
|
||||
document.body.appendChild(div);
|
||||
|
||||
describe('edge click state', () => {
|
||||
it.only('edge ', () => {
|
||||
G6.registerBehavior("active-edge", {
|
||||
getEvents() {
|
||||
return {
|
||||
"edge:click": "onEdgeSelect",
|
||||
"edge:mouseenter": "onEdgeHover",
|
||||
"edge:mouseleave": "onEdgeLeave",
|
||||
"canvas:mousedown": "clearSelectedEdge"
|
||||
};
|
||||
},
|
||||
onEdgeSelect(evt) {
|
||||
console.log('mousedown')
|
||||
const item = evt.item;
|
||||
if (item.hasState("select")) {
|
||||
this.graph.setItemState(item, 'select', false);
|
||||
return;
|
||||
}
|
||||
this.graph.setItemState(item, 'select', true);
|
||||
},
|
||||
onEdgeHover(evt) {
|
||||
console.log('hover')
|
||||
const item = evt.item;
|
||||
if (item.hasState("select")) {
|
||||
return false;
|
||||
}
|
||||
this.graph.setItemState(item, 'hover', true);
|
||||
},
|
||||
onEdgeLeave(evt) {
|
||||
console.log('leave')
|
||||
const item = evt.item;
|
||||
this.graph.setItemState(item, 'hover', false);
|
||||
},
|
||||
clearSelectedEdge(evt) {
|
||||
console.log('clear')
|
||||
const edges = this.graph.findAllByState("edge", 'select');
|
||||
edges.forEach(edge => {
|
||||
this.graph.setItemState(edge, 'select', false);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const graph = new G6.Graph({
|
||||
container: "container",
|
||||
width: 500,
|
||||
height: 500,
|
||||
defaultEdge: {
|
||||
type: "line",
|
||||
style: {
|
||||
stroke: "#24A0FF",
|
||||
radius: 4,
|
||||
offset: 15,
|
||||
lineWidth: 2,
|
||||
lineAppendWidth: 4,
|
||||
cursor: "pointer",
|
||||
endArrow: {
|
||||
path: "M 0,0 L 7,3 L 5,0 L 7,-3 Z",
|
||||
fill: "#24A0FF"
|
||||
}
|
||||
}
|
||||
},
|
||||
edgeStateStyles: {
|
||||
hover: {
|
||||
stroke: "#0ff",
|
||||
endArrow: {
|
||||
fill: "#FF7868"
|
||||
}
|
||||
},
|
||||
select: {
|
||||
stroke: "#FF7868",
|
||||
endArrow: {
|
||||
fill: "#FF7868"
|
||||
}
|
||||
}
|
||||
},
|
||||
modes: {
|
||||
default: [
|
||||
'drag-node',
|
||||
'active-edge'
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
graph.read({
|
||||
nodes: [
|
||||
{ id: '1', x: 100, y: 100},
|
||||
{ id: '2', x: 100, y: 220}
|
||||
],
|
||||
edges: [
|
||||
{ source: '1', target: '2' }
|
||||
]
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('dragenter dragleave', () => {
|
||||
const data = {
|
||||
nodes: [{
|
||||
|
Loading…
Reference in New Issue
Block a user