mirror of
https://gitee.com/antv/g6.git
synced 2024-11-30 02:38:20 +08:00
feat: container of plugins with dom id; fix: combo zIndex problem; fix: webworker updateLayoutCfg problem;
This commit is contained in:
parent
906d1653c0
commit
f033c9f8e2
@ -5,8 +5,12 @@
|
||||
- feat: graphin force;
|
||||
- feat: updateChildren API for TreeGraph;
|
||||
- feat: louvain clustering algorithm;
|
||||
- feat: container of plugins with dom id;
|
||||
- fix: text redidual problem, closes: #2045 #2193;
|
||||
- fix: graph on callback parameter type problem, closes: #2250;
|
||||
- fix: combo zIndex problem;
|
||||
- fix: webworker updateLayoutCfg problem;
|
||||
- fix: drag-canvas and click node on mobile;
|
||||
|
||||
#### 3.8.5
|
||||
- fix: get fontFamily of the window in global leads to DOM depending when using bigfish;
|
||||
|
@ -92,6 +92,7 @@ export default {
|
||||
|
||||
if (dragCombos.length === 0) {
|
||||
this.targets.push(item);
|
||||
|
||||
} else {
|
||||
this.targets = combos;
|
||||
}
|
||||
|
@ -1731,7 +1731,7 @@ export default class Graph extends EventEmitter implements IGraph {
|
||||
* @param {String | INode | ICombo} item 需要被更新的 Combo 或 节点 id
|
||||
* @param {string | undefined} parentId 新的父 combo id,undefined 代表没有父 combo
|
||||
*/
|
||||
public updateComboTree(item: string | INode | ICombo, parentId?: string | undefined) {
|
||||
public updateComboTree(item: string | INode | ICombo, parentId?: string | undefined, stack: boolean = true) {
|
||||
const self = this;
|
||||
this.set('comboSorted', false);
|
||||
let uItem: INode | ICombo;
|
||||
@ -1744,8 +1744,11 @@ export default class Graph extends EventEmitter implements IGraph {
|
||||
const model = uItem.getModel();
|
||||
const oldParentId = (model.comboId as string) || (model.parentId as string);
|
||||
|
||||
let type = '';
|
||||
if (uItem.getType) type = uItem.getType();
|
||||
|
||||
// 若 item 是 Combo,且 parentId 是其子孙 combo 的 id,则警告并终止
|
||||
if (parentId && uItem.getType && uItem.getType() === 'combo') {
|
||||
if (parentId && type === 'combo') {
|
||||
const comboTrees = this.get('comboTrees');
|
||||
let valid = true;
|
||||
let itemSubTree;
|
||||
@ -1775,7 +1778,34 @@ export default class Graph extends EventEmitter implements IGraph {
|
||||
}
|
||||
}
|
||||
|
||||
// 当 combo 存在parentId 或 comboId 时,才将其移除
|
||||
if (stack && this.get('enabledStack')) {
|
||||
const beforeData: GraphData = {}, afterData: GraphData = {};
|
||||
if (type === 'combo') {
|
||||
beforeData.combos = [{
|
||||
id: model.id,
|
||||
parentId: (model as ComboConfig).parentId
|
||||
}];
|
||||
afterData.combos = [{
|
||||
id: model.id,
|
||||
parentId
|
||||
}];
|
||||
} else if (type === 'node') {
|
||||
beforeData.nodes = [{
|
||||
id: model.id,
|
||||
parentId: (model as NodeConfig).comboId
|
||||
}];
|
||||
afterData.nodes = [{
|
||||
id: model.id,
|
||||
parentId
|
||||
}];
|
||||
}
|
||||
this.pushStack('updateComboTree', {
|
||||
before: beforeData,
|
||||
after: afterData
|
||||
});
|
||||
}
|
||||
|
||||
// 当 combo 存在 parentId 或 comboId 时,才将其移除
|
||||
if (model.parentId || model.comboId) {
|
||||
const combo = this.findById((model.parentId || model.comboId) as string) as ICombo;
|
||||
if (combo) {
|
||||
@ -1783,9 +1813,6 @@ export default class Graph extends EventEmitter implements IGraph {
|
||||
}
|
||||
}
|
||||
|
||||
let type = '';
|
||||
if (uItem.getType) type = uItem.getType();
|
||||
|
||||
if (type === 'combo') {
|
||||
model.parentId = parentId;
|
||||
} else if (type === 'node') {
|
||||
|
@ -220,7 +220,7 @@ export interface IGraph extends EventEmitter {
|
||||
* @param {string | INode | ICombo} item 需要被更新的 Combo 或 节点 id
|
||||
* @param {string | undefined} parentId 新的父 combo id,undefined 代表没有父 combo
|
||||
*/
|
||||
updateComboTree(item: string | INode | ICombo, parentId?: string | undefined): void;
|
||||
updateComboTree(item: string | INode | ICombo, parentId?: string | undefined, stack?: boolean): void;
|
||||
|
||||
/**
|
||||
* 解散 combo
|
||||
|
@ -15,6 +15,7 @@ import {
|
||||
Indexable,
|
||||
ComboConfig,
|
||||
ITEM_TYPE,
|
||||
TreeGraphData
|
||||
} from '../types';
|
||||
|
||||
// item 的配置项
|
||||
@ -133,7 +134,7 @@ export interface IItemBase {
|
||||
* 节点 / 边 / Combo 的数据模型
|
||||
* @return {Object} 数据模型
|
||||
*/
|
||||
getModel(): NodeConfig | EdgeConfig | ComboConfig;
|
||||
getModel(): NodeConfig | EdgeConfig | ComboConfig | TreeGraphData;
|
||||
|
||||
/**
|
||||
* 节点类型
|
||||
|
@ -209,9 +209,12 @@ export default class GraphinForceGPULayout extends BaseLayout {
|
||||
centerGravities.push(nodeGravity[2]);
|
||||
})
|
||||
|
||||
// 每个几点的额外属性占两格,分别是:mass, degree, nodeSterngth, centerX, centerY, gravity, 0, 0
|
||||
const nodeAttributeArray = arrayToTextureData([
|
||||
masses, self.degrees, nodeStrengths,
|
||||
// 每个节点的额外属性占两个数组各一格,nodeAttributeArray1 中是:mass, degree, nodeSterngth, 0
|
||||
const nodeAttributeArray1 = arrayToTextureData([
|
||||
masses, self.degrees, nodeStrengths
|
||||
]);
|
||||
// nodeAttributeArray2 中是:centerX, centerY, gravity, 0,
|
||||
const nodeAttributeArray2 = arrayToTextureData([
|
||||
centerXs, centerYs, centerGravities
|
||||
]);
|
||||
|
||||
@ -236,7 +239,7 @@ export default class GraphinForceGPULayout extends BaseLayout {
|
||||
// TODO: 最终的预编译代码放入到 graphinForceShader.ts 中直接引入,不再需要下面三行
|
||||
const compiler = new Compiler();
|
||||
const graphinForceBundle = compiler.compileBundle(graphinForceCode);
|
||||
console.log(graphinForceBundle);
|
||||
console.log(graphinForceBundle.toString());
|
||||
|
||||
const onLayoutEnd = self.onLayoutEnd;
|
||||
|
||||
@ -250,7 +253,8 @@ export default class GraphinForceGPULayout extends BaseLayout {
|
||||
u_minMovement: self.minMovement,
|
||||
u_coulombDisScale: self.coulombDisScale,
|
||||
u_factor: self.factor,
|
||||
u_NodeAttributeArray: nodeAttributeArray,
|
||||
u_NodeAttributeArray1: nodeAttributeArray1,
|
||||
u_NodeAttributeArray2: nodeAttributeArray2,
|
||||
MAX_EDGE_PER_VERTEX: maxEdgePerVetex,
|
||||
VERTEX_COUNT: numParticles,
|
||||
u_interval: self.interval // 每次迭代更新,首次设置为 interval,在 onIterationCompleted 中更新
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
export const graphinForceCode = `
|
||||
import { globalInvocationID } from 'g-webgpu';
|
||||
|
||||
@ -26,7 +25,10 @@ class GraphinForce {
|
||||
u_factor: float;
|
||||
|
||||
@in
|
||||
u_NodeAttributeArray: vec4[];
|
||||
u_NodeAttributeArray1: vec4[];
|
||||
|
||||
@in
|
||||
u_NodeAttributeArray2: vec4[];
|
||||
|
||||
@in
|
||||
u_EdgeAttributeArray: vec4[];
|
||||
@ -48,8 +50,8 @@ class GraphinForce {
|
||||
const n_dist = dist * this.u_coulombDisScale;
|
||||
const direx = vx / dist;
|
||||
const direy = vy / dist;
|
||||
const attributesi = this.u_NodeAttributeArray[2 * i];
|
||||
const attributesj = this.u_NodeAttributeArray[2 * j];
|
||||
const attributesi = this.u_NodeAttributeArray1[2 * i];
|
||||
const attributesj = this.u_NodeAttributeArray1[(int)2 * j];
|
||||
const massi = attributesi[0];
|
||||
const nodeStrengthi = attributesi[2];
|
||||
const nodeStrengthj = attributesj[2];
|
||||
@ -63,14 +65,14 @@ class GraphinForce {
|
||||
return [ax, ay];
|
||||
}
|
||||
|
||||
calcGravity(i: int, currentNode: vec4, attributes: vec4): vec2 {
|
||||
// note: attributes = [mass, degree, nodeSterngth, centerX, centerY, gravity, 0, 0]
|
||||
calcGravity(i: int, currentNode: vec4, attributes2: vec4): vec2 {
|
||||
// note: attributes2 = [centerX, centerY, gravity, 0]
|
||||
|
||||
const vx = currentNode[0] - attributes[3];
|
||||
const vy = currentNode[1] - attributes[4];
|
||||
const vx = currentNode[0] - attributes2[0];
|
||||
const vy = currentNode[1] - attributes2[1];
|
||||
|
||||
const ax = vx * attributes[5];
|
||||
const ay = vy * attributes[5];
|
||||
const ax = vx * attributes[3];
|
||||
const ay = vy * attributes[3];
|
||||
|
||||
|
||||
|
||||
@ -85,10 +87,10 @@ class GraphinForce {
|
||||
return [ax, ay];
|
||||
}
|
||||
|
||||
calcAttractive(i: int, currentNode: vec4, attributes: vec4): vec2 {
|
||||
// note: attributes = [mass, degree, nodeSterngth, centerX, centerY, gravity, 0, 0]
|
||||
calcAttractive(i: int, currentNode: vec4, attributes1: vec4): vec2 {
|
||||
// note: attributes = [mass, degree, nodeSterngth, 0]
|
||||
|
||||
const mass = attributes[0];
|
||||
const mass = attributes1[0];
|
||||
let ax = 0, ay = 0;
|
||||
const arr_offset = int(floor(currentNode[2] + 0.5));
|
||||
const length = int(floor(currentNode[3] + 0.5));
|
||||
@ -131,8 +133,9 @@ class GraphinForce {
|
||||
return;
|
||||
}
|
||||
|
||||
// 每个节点属性占两小格
|
||||
const nodeAttributes = this.u_NodeAttributeArray[2 * i];
|
||||
// 每个节点属性占两个数组中各一格
|
||||
const nodeAttributes1 = this.u_NodeAttributeArray1[2 * i];
|
||||
const nodeAttributes2 = this.u_NodeAttributeArray2[2 * i];
|
||||
|
||||
// repulsive
|
||||
const repulsive = this.calcRepulsive(i, currentNode);
|
||||
@ -140,17 +143,16 @@ class GraphinForce {
|
||||
ay += repulsive[1];
|
||||
|
||||
// attractive
|
||||
const attractive = this.calcAttractive(i, currentNode, nodeAttributes);
|
||||
const attractive = this.calcAttractive(i, currentNode, nodeAttributes1);
|
||||
ax += attractive[0];
|
||||
ay += attractive[1];
|
||||
|
||||
// gravity
|
||||
const gravity = this.calcGravity(i, currentNode, nodeAttributes);
|
||||
const gravity = this.calcGravity(i, currentNode, nodeAttributes2);
|
||||
ax -= gravity[0];
|
||||
ay -= gravity[1];
|
||||
|
||||
// speed
|
||||
const interval = 0.02; // max(0.02, 0.22 - 0.002 * this.u_iter);
|
||||
const param = this.u_interval * this.u_damping;
|
||||
let vx = ax * param;
|
||||
let vy = ay * param;
|
||||
|
@ -5,7 +5,7 @@ import Graph from '../graph/graph';
|
||||
import { IG6GraphEvent } from '../types';
|
||||
|
||||
export interface IPluginBaseConfig {
|
||||
container?: HTMLDivElement | null;
|
||||
container?: HTMLDivElement | string | null;
|
||||
className?: string;
|
||||
graph?: Graph;
|
||||
[key: string]: any;
|
||||
|
@ -81,7 +81,10 @@ export default class ImageMiniMap extends Base {
|
||||
const { graph } = cfgs;
|
||||
if (this.destroyed) return;
|
||||
|
||||
const containerDOM = this.get('container');
|
||||
let containerDOM = this.get('container');
|
||||
if (isString(containerDOM)) {
|
||||
containerDOM = document.getElementById(containerDOM) as HTMLDivElement;
|
||||
}
|
||||
const viewport = createDOM(
|
||||
`<div class=${cfgs.viewportClassName}
|
||||
style='position:absolute;
|
||||
|
@ -77,6 +77,9 @@ export default class Menu extends Base {
|
||||
if (!container) {
|
||||
container = this.get('graph').get('container');
|
||||
}
|
||||
if (isString(container)) {
|
||||
container = document.getElementById(container) as HTMLDivElement;
|
||||
}
|
||||
container.appendChild(menu);
|
||||
|
||||
this.set('menu', menu);
|
||||
@ -193,6 +196,9 @@ export default class Menu extends Base {
|
||||
if (!container) {
|
||||
container = this.get('graph').get('container');
|
||||
}
|
||||
if (isString(container)) {
|
||||
container = document.getElementById(container) as HTMLDivElement;
|
||||
}
|
||||
container.removeChild(menu);
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import { VALUE_CHANGE } from './constant'
|
||||
import { GraphData, IG6GraphEvent, ShapeStyle, TimeBarType } from '../../types';
|
||||
import { Interval } from './trend';
|
||||
import { ControllerCfg } from './controllerBtn';
|
||||
import { isString } from '@antv/util';
|
||||
|
||||
// simple 版本默认高度
|
||||
const DEFAULT_SIMPLE_HEIGHT = 8
|
||||
@ -109,7 +110,7 @@ export default class TimeBar extends Base {
|
||||
const { width, height } = this._cfgs
|
||||
const className: string = this.get('className') || 'g6-component-timebar';
|
||||
|
||||
const container: HTMLDivElement | null = this.get('container');
|
||||
let container: HTMLDivElement | null | string = this.get('container');
|
||||
|
||||
const graphContainer = this.get('graph').get('container');
|
||||
|
||||
@ -118,6 +119,9 @@ export default class TimeBar extends Base {
|
||||
timeBarContainer = createDOM(`<div class='${className}'></div>`);
|
||||
modifyCSS(timeBarContainer, { position: 'relative' });
|
||||
} else {
|
||||
if (isString(container)) {
|
||||
container = document.getElementById(container) as HTMLDivElement;
|
||||
}
|
||||
timeBarContainer = container;
|
||||
}
|
||||
|
||||
@ -308,6 +312,9 @@ export default class TimeBar extends Base {
|
||||
if (!container) {
|
||||
container = this.get('graph').get('container');
|
||||
}
|
||||
if (isString(container)) {
|
||||
container = document.getElementById(container) as HTMLDivElement;
|
||||
}
|
||||
container.removeChild(timeBarContainer);
|
||||
}
|
||||
}
|
||||
|
@ -104,6 +104,9 @@ export default class ToolBar extends Base {
|
||||
if (!container) {
|
||||
container = this.get('graph').get('container');
|
||||
}
|
||||
if (isString(container)) {
|
||||
container = document.getElementById(container) as HTMLDivElement;
|
||||
}
|
||||
|
||||
container!.appendChild(toolBarDOM);
|
||||
this.set('toolBar', toolBarDOM);
|
||||
@ -249,6 +252,15 @@ export default class ToolBar extends Base {
|
||||
});
|
||||
});
|
||||
break;
|
||||
case 'updateComboTree':
|
||||
Object.keys(data).forEach(key => {
|
||||
const array = data[key];
|
||||
if (!array) return;
|
||||
array.forEach(model => {
|
||||
graph.updateComboTree(model.id, model.parentId, false);
|
||||
});
|
||||
});
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
@ -334,6 +346,15 @@ export default class ToolBar extends Base {
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'updateComboTree':
|
||||
Object.keys(data).forEach(key => {
|
||||
const array = data[key];
|
||||
if (!array) return;
|
||||
array.forEach(model => {
|
||||
graph.updateComboTree(model.id, model.parentId, false);
|
||||
});
|
||||
});
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
@ -387,6 +408,9 @@ export default class ToolBar extends Base {
|
||||
if (!container) {
|
||||
container = this.get('graph').get('container');
|
||||
}
|
||||
if (isString(container)) {
|
||||
container = document.getElementById(container) as HTMLDivElement;
|
||||
}
|
||||
container.removeChild(toolBar);
|
||||
}
|
||||
|
||||
|
@ -79,6 +79,9 @@ export default class Tooltip extends Base {
|
||||
if (!container) {
|
||||
container = this.get('graph').get('container');
|
||||
}
|
||||
if (isString(container)) {
|
||||
container = document.getElementById(container) as HTMLDivElement;
|
||||
}
|
||||
|
||||
modifyCSS(tooltip, { position: 'absolute', visibility: 'hidden' });
|
||||
container.appendChild(tooltip);
|
||||
@ -196,6 +199,9 @@ export default class Tooltip extends Base {
|
||||
if (!container) {
|
||||
container = this.get('graph').get('container');
|
||||
}
|
||||
if (isString(container)) {
|
||||
container = document.getElementById(container) as HTMLDivElement;
|
||||
}
|
||||
container.removeChild(tooltip);
|
||||
}
|
||||
}
|
||||
|
@ -400,6 +400,7 @@ export interface TreeGraphData {
|
||||
[key: string]: ShapeStyle;
|
||||
};
|
||||
stateStyles?: StateStyles;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface NodeConfig extends ModelConfig {
|
||||
|
@ -530,8 +530,9 @@ export const plainCombosToTrees = (array: ComboConfig[], nodes?: NodeConfig[]) =
|
||||
});
|
||||
|
||||
// assign the depth for each element
|
||||
let maxDepth = 0;
|
||||
result.forEach((tree: ComboTree) => {
|
||||
tree.depth = 0;
|
||||
tree.depth = maxDepth + 10;
|
||||
traverse<ComboTree>(tree, (child) => {
|
||||
let parent;
|
||||
const itemType = addedMap[child.id].itemType;
|
||||
@ -541,11 +542,12 @@ export const plainCombosToTrees = (array: ComboConfig[], nodes?: NodeConfig[]) =
|
||||
parent = addedMap[child.parentId];
|
||||
}
|
||||
if (parent) {
|
||||
if (itemType === 'node') child.depth = parent.depth + 1;
|
||||
else child.depth = parent.depth + 2;
|
||||
if (itemType === 'node') child.depth = maxDepth + 1;
|
||||
else child.depth = maxDepth + 10;
|
||||
} else {
|
||||
child.depth = 0;
|
||||
child.depth = maxDepth + 10;
|
||||
}
|
||||
if (maxDepth < child.depth) maxDepth = child.depth;
|
||||
const oriNodeModel = nodeMap[child.id];
|
||||
if (oriNodeModel) {
|
||||
oriNodeModel.depth = child.depth;
|
||||
|
@ -16,6 +16,19 @@ import {
|
||||
} from '../types';
|
||||
import { each } from '@antv/util';
|
||||
|
||||
/**
|
||||
* 对比对象,用于对象数组排序
|
||||
* @param {string} attributeName 排序依据的字段名称
|
||||
* @param {number} min 最小值
|
||||
* @param {number} max 最大值
|
||||
* @return {boolean} bool 布尔
|
||||
*/
|
||||
export const compare = (attributeName: string) => {
|
||||
return (m, n) => {
|
||||
return m[attributeName] - n[attributeName];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 是否在区间内
|
||||
* @param {number} value 值
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import G6 from '../../../src';
|
||||
import { IGraph } from '../../../src/interface/graph';
|
||||
import { NodeConfig } from '../../../src/types';
|
||||
|
||||
let graph: IGraph = null;
|
||||
let showNodes = [];
|
||||
@ -256,7 +257,7 @@ const DecisionTree = () => {
|
||||
|
||||
graph.on('node:mouseenter', (e) => {
|
||||
const item = e.item;
|
||||
const model = item.getModel();
|
||||
const model = item.getModel() as NodeConfig;
|
||||
if (model.level === 0) {
|
||||
return;
|
||||
}
|
||||
@ -270,14 +271,14 @@ const DecisionTree = () => {
|
||||
});
|
||||
graph.setItemState(item, 'dark', false);
|
||||
model.light = true;
|
||||
const tags = model.tags;
|
||||
const tags: string[] = model.tags as string[];
|
||||
const findTagsMap = new Map();
|
||||
let mid = 0;
|
||||
|
||||
let fTag = '';
|
||||
// if the model is F node, find the leaves of it
|
||||
if (!model.isLeaf && model.level !== 0) {
|
||||
fTag = model.tag;
|
||||
fTag = model.tag as string;
|
||||
nodeItems.forEach((item) => {
|
||||
const itemModel = item.getModel();
|
||||
if (!itemModel.isLeaf) return;
|
||||
@ -350,7 +351,7 @@ const DecisionTree = () => {
|
||||
curShowNodes = [];
|
||||
curShowEdges = [];
|
||||
const item = e.item;
|
||||
const model = item.getModel();
|
||||
const model = item.getModel() as NodeConfig;
|
||||
if (!model.isLeaf && model.level !== 0) {
|
||||
return;
|
||||
}
|
||||
@ -431,8 +432,8 @@ const DecisionTree = () => {
|
||||
}
|
||||
if (isChild) {
|
||||
const randomAngle = Math.random() * 2 * Math.PI;
|
||||
node.x = model.x + (Math.cos(randomAngle) * model.size) / 2 + 10;
|
||||
node.y = model.y + (Math.sin(randomAngle) * model.size) / 2 + 10;
|
||||
node.x = model.x + (Math.cos(randomAngle) * (model.size as number)) / 2 + 10;
|
||||
node.y = model.y + (Math.sin(randomAngle) * (model.size as number)) / 2 + 10;
|
||||
// const dist = (model.x - node.x) * (model.x - node.x) + (model.y - node.y) * (model.y - node.y);
|
||||
|
||||
if (!node.style) node.style = {};
|
||||
|
@ -2,6 +2,7 @@ import React, { useEffect } from 'react';
|
||||
import G6 from '../../../src';
|
||||
import { IGraph } from '../../../src/interface/graph';
|
||||
import { GraphData } from '../../../src/types';
|
||||
import { ICombo } from '../../../src/interface/item';
|
||||
|
||||
let graph: IGraph = null;
|
||||
|
||||
@ -327,7 +328,7 @@ const DagreCombo = () => {
|
||||
// }, 500);
|
||||
|
||||
graph.on('combo:click', function (e) {
|
||||
graph.collapseExpandCombo(e.item);
|
||||
graph.collapseExpandCombo(e.item as ICombo);
|
||||
graph.refreshPositions();
|
||||
});
|
||||
|
||||
|
@ -7,37 +7,19 @@ let graph: IGraph = null;
|
||||
|
||||
const data: GraphData = {
|
||||
nodes: [
|
||||
{
|
||||
id: 'node1',
|
||||
label: 'node1',
|
||||
x: 250,
|
||||
y: 150,
|
||||
comboId: 'combo',
|
||||
},
|
||||
{
|
||||
id: 'node2',
|
||||
label: 'node2',
|
||||
x: 350,
|
||||
y: 150,
|
||||
comboId: 'combo',
|
||||
},
|
||||
],
|
||||
combos: [
|
||||
{
|
||||
id: 'combo',
|
||||
label: 'Combo ',
|
||||
},
|
||||
{
|
||||
id: 'combo1',
|
||||
label: 'Combo',
|
||||
},
|
||||
{ id: 'node1', x: 350, y: 200, comboId: 'combo1', label: 'node1' },
|
||||
{ id: 'node2', x: 350, y: 250, comboId: 'combo1', label: 'node2' },
|
||||
{ id: 'node3', x: 100, y: 200, comboId: 'combo3', label: 'node3' },
|
||||
],
|
||||
edges: [
|
||||
{
|
||||
id: 'edge1',
|
||||
source: 'combo',
|
||||
target: 'combo1',
|
||||
},
|
||||
{ source: 'node1', target: 'node2' },
|
||||
{ source: 'node1', target: 'node3' },
|
||||
{ source: 'combo1', target: 'node3' },
|
||||
],
|
||||
combos: [
|
||||
{ id: 'combo1', label: 'Combo 1', parentId: 'combo2' },
|
||||
{ id: 'combo2', label: 'Combo 2' },
|
||||
{ id: 'combo3', label: 'Combo 3' },
|
||||
],
|
||||
};
|
||||
|
||||
|
@ -2,6 +2,7 @@ import React, { useEffect } from 'react';
|
||||
import G6 from '../../../src';
|
||||
import { IGraph } from '../../../src/interface/graph';
|
||||
import { GraphData } from '../../../src/types';
|
||||
import { ICombo } from '../../../src/interface/item';
|
||||
|
||||
let graph: IGraph = null;
|
||||
|
||||
@ -140,7 +141,7 @@ const Edges2 = () => {
|
||||
graph.data(data);
|
||||
graph.render();
|
||||
graph.on('combo:click', function (e) {
|
||||
graph.collapseExpandCombo(e.item);
|
||||
graph.collapseExpandCombo(e.item as ICombo);
|
||||
graph.refreshPositions();
|
||||
});
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
import G6 from '../../../src';
|
||||
import { IEdge } from '../../../src/interface/item';
|
||||
// import "./styles.css";
|
||||
|
||||
export default class ForceLayout extends Component {
|
||||
@ -823,7 +824,7 @@ export default class ForceLayout extends Component {
|
||||
const part1NodeMap = new Map();
|
||||
const part2NodeMap = new Map();
|
||||
// separate the nodes and init the positions
|
||||
nodes.forEach(function(node, i) {
|
||||
nodes.forEach(function (node, i) {
|
||||
if (node.name === "MySQL") {
|
||||
part1Nodes.push(node);
|
||||
part1NodeMap.set(node.id, i);
|
||||
@ -843,7 +844,7 @@ export default class ForceLayout extends Component {
|
||||
// if (direction === "vertical") {
|
||||
// begin = center[0] - height / 2;
|
||||
// }
|
||||
part1Nodes.forEach(function(p1n, i) {
|
||||
part1Nodes.forEach(function (p1n, i) {
|
||||
if (direction === "horizontal") {
|
||||
p1n.x = part1Pos;
|
||||
p1n.y = begin + i * (nodeSep + nodeSize);
|
||||
@ -852,7 +853,7 @@ export default class ForceLayout extends Component {
|
||||
p1n.y = part1Pos;
|
||||
}
|
||||
});
|
||||
part2Nodes.forEach(function(p2n, i) {
|
||||
part2Nodes.forEach(function (p2n, i) {
|
||||
if (direction === "horizontal") {
|
||||
p2n.x = part2Pos;
|
||||
p2n.y = begin + i * (nodeSep + nodeSize);
|
||||
@ -902,7 +903,7 @@ export default class ForceLayout extends Component {
|
||||
const part3NodeMap = new Map();
|
||||
const part4NodeMap = new Map();
|
||||
// separate the nodes and init the positions
|
||||
nodes.forEach(function(node, i) {
|
||||
nodes.forEach(function (node, i) {
|
||||
if (node.name === "MySQL") {
|
||||
part1Nodes.push(node);
|
||||
part1NodeMap.set(node.id, i);
|
||||
@ -941,27 +942,27 @@ export default class ForceLayout extends Component {
|
||||
// if (direction === "vertical") {
|
||||
// begin = center[0] - height / 2;
|
||||
// }
|
||||
part1Nodes.forEach(function(p1n, i) {
|
||||
part1Nodes.forEach(function (p1n, i) {
|
||||
if (direction === "rect") {
|
||||
p1n.x = xbegin - nodeSize;
|
||||
p1n.y = hbegin + i * (nodeSep + nodeSize);
|
||||
// console.log(p1n);
|
||||
}
|
||||
});
|
||||
part2Nodes.forEach(function(p2n, i) {
|
||||
part2Nodes.forEach(function (p2n, i) {
|
||||
if (direction === "rect") {
|
||||
p2n.x = xbegin + width;
|
||||
p2n.y = hbegin + i * (nodeSep + nodeSize);
|
||||
// console.log(p2n);
|
||||
}
|
||||
});
|
||||
part3Nodes.forEach(function(p3n, i) {
|
||||
part3Nodes.forEach(function (p3n, i) {
|
||||
if (direction === "rect") {
|
||||
p3n.x = xbegin + i * (nodeSep + nodeSize);
|
||||
p3n.y = part3Pos;
|
||||
}
|
||||
});
|
||||
part4Nodes.forEach(function(p4n, i) {
|
||||
part4Nodes.forEach(function (p4n, i) {
|
||||
if (direction === "rect") {
|
||||
p4n.x = xbegin + i * (nodeSep + nodeSize);
|
||||
p4n.y = part4Pos;
|
||||
@ -979,121 +980,121 @@ export default class ForceLayout extends Component {
|
||||
};
|
||||
|
||||
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: ''
|
||||
* }
|
||||
*/
|
||||
// console.log('cfg.leftIcon', cfg.leftIcon);
|
||||
// if (cfg.leftIcon) {
|
||||
// const { style, img } = cfg.leftIcon;
|
||||
group.addShape('rect', {
|
||||
attrs: {
|
||||
x: 1,
|
||||
y: 1,
|
||||
width: 38,
|
||||
height: styles.height - 2,
|
||||
fill: '#ffffff',
|
||||
// ...style,
|
||||
},
|
||||
});
|
||||
// group.addShape('rect', {
|
||||
// attrs: {
|
||||
// x: 180,
|
||||
// y: 1,
|
||||
// width: 22,
|
||||
// height: styles.height - 2,
|
||||
// fill: '#ffffff',
|
||||
// // ...style,
|
||||
// },
|
||||
// });
|
||||
|
||||
group.addShape('image', {
|
||||
attrs: {
|
||||
x: 1,
|
||||
y: 1,
|
||||
width: 38,
|
||||
height: 30,
|
||||
// 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: -6,
|
||||
y: 15,
|
||||
r: 6,
|
||||
stroke: '#73d13d',
|
||||
cursor: 'pointer',
|
||||
symbol: EXPAND_ICON,
|
||||
},
|
||||
name: 'add-tableData',
|
||||
});
|
||||
group.addShape('marker', {
|
||||
attrs: {
|
||||
x: 46,
|
||||
y: 15,
|
||||
r: 6,
|
||||
stroke: '#73d13d',
|
||||
cursor: 'pointer',
|
||||
symbol: EXPAND_ICON,
|
||||
},
|
||||
name: 'add-fieldData',
|
||||
});
|
||||
group.addShape('marker', {
|
||||
attrs: {
|
||||
x: 190,
|
||||
y: 22,
|
||||
r: 6,
|
||||
stroke: '#ffffff',
|
||||
cursor: 'pointer',
|
||||
symbol: EXPAND_ICON,
|
||||
},
|
||||
name: 'show-tableData',
|
||||
});
|
||||
|
||||
if (cfg.label) {
|
||||
group.addShape('text', {
|
||||
attrs: {
|
||||
...labelCfg.style,
|
||||
text: cfg.label,
|
||||
x: 100,
|
||||
y: 20,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return keyShape;
|
||||
},
|
||||
'icon-node',
|
||||
{
|
||||
options: {
|
||||
size: [60, 20],
|
||||
stroke: '#91d5ff',
|
||||
fill: '#91d5ff',
|
||||
},
|
||||
'rect',
|
||||
);
|
||||
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: ''
|
||||
* }
|
||||
*/
|
||||
// console.log('cfg.leftIcon', cfg.leftIcon);
|
||||
// if (cfg.leftIcon) {
|
||||
// const { style, img } = cfg.leftIcon;
|
||||
group.addShape('rect', {
|
||||
attrs: {
|
||||
x: 1,
|
||||
y: 1,
|
||||
width: 38,
|
||||
height: styles.height - 2,
|
||||
fill: '#ffffff',
|
||||
// ...style,
|
||||
},
|
||||
});
|
||||
// group.addShape('rect', {
|
||||
// attrs: {
|
||||
// x: 180,
|
||||
// y: 1,
|
||||
// width: 22,
|
||||
// height: styles.height - 2,
|
||||
// fill: '#ffffff',
|
||||
// // ...style,
|
||||
// },
|
||||
// });
|
||||
|
||||
group.addShape('image', {
|
||||
attrs: {
|
||||
x: 1,
|
||||
y: 1,
|
||||
width: 38,
|
||||
height: 30,
|
||||
// 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: -6,
|
||||
y: 15,
|
||||
r: 6,
|
||||
stroke: '#73d13d',
|
||||
cursor: 'pointer',
|
||||
symbol: EXPAND_ICON,
|
||||
},
|
||||
name: 'add-tableData',
|
||||
});
|
||||
group.addShape('marker', {
|
||||
attrs: {
|
||||
x: 46,
|
||||
y: 15,
|
||||
r: 6,
|
||||
stroke: '#73d13d',
|
||||
cursor: 'pointer',
|
||||
symbol: EXPAND_ICON,
|
||||
},
|
||||
name: 'add-fieldData',
|
||||
});
|
||||
group.addShape('marker', {
|
||||
attrs: {
|
||||
x: 190,
|
||||
y: 22,
|
||||
r: 6,
|
||||
stroke: '#ffffff',
|
||||
cursor: 'pointer',
|
||||
symbol: EXPAND_ICON,
|
||||
},
|
||||
name: 'show-tableData',
|
||||
});
|
||||
|
||||
if (cfg.label) {
|
||||
group.addShape('text', {
|
||||
attrs: {
|
||||
...labelCfg.style,
|
||||
text: cfg.label,
|
||||
x: 100,
|
||||
y: 20,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return keyShape;
|
||||
},
|
||||
},
|
||||
'rect',
|
||||
);
|
||||
|
||||
G6.registerEdge(
|
||||
'circle-running',
|
||||
@ -1140,7 +1141,7 @@ export default class ForceLayout extends Component {
|
||||
// 3.图实例化
|
||||
const width = document.getElementById('container').scrollWidth;
|
||||
const height = document.getElementById('container').scrollHeight || 500;
|
||||
|
||||
|
||||
const minimap = new G6.Minimap({
|
||||
size: [300, 300],
|
||||
});
|
||||
@ -1157,14 +1158,14 @@ export default class ForceLayout extends Component {
|
||||
// },
|
||||
offset: 30
|
||||
}, {
|
||||
type: 'edge-tooltip',
|
||||
// formatText: function formatText(model, e) {
|
||||
// const edge = e.item;
|
||||
// return ('来源:' + edge.getSource().getModel().name +
|
||||
// '<br/>去向:' + edge.getTarget().getModel().name)
|
||||
// },
|
||||
offset: 30
|
||||
}, 'activate-relations'],
|
||||
type: 'edge-tooltip',
|
||||
// formatText: function formatText(model, e) {
|
||||
// const edge = e.item;
|
||||
// return ('来源:' + edge.getSource().getModel().name +
|
||||
// '<br/>去向:' + edge.getTarget().getModel().name)
|
||||
// },
|
||||
offset: 30
|
||||
}, 'activate-relations'],
|
||||
},
|
||||
layout: {
|
||||
type: 'circular',
|
||||
@ -1292,15 +1293,15 @@ export default class ForceLayout extends Component {
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
}
|
||||
}
|
||||
})
|
||||
// 7.连线的交互事件
|
||||
graph.on('edge:mouseenter', (evt) => {
|
||||
const { item } = evt;
|
||||
graph.setItemState(item, 'hover', true);
|
||||
// 获取连线起点和终点坐标的对象后调用函数
|
||||
const edge = evt.item;
|
||||
getCubicController (edge.getSource().getModel(), edge.getTarget().getModel());
|
||||
const edge: IEdge = evt.item as IEdge;
|
||||
getCubicController(edge.getSource().getModel(), edge.getTarget().getModel());
|
||||
});
|
||||
graph.on('edge:mouseleave', (evt) => {
|
||||
const { item } = evt;
|
||||
@ -1312,17 +1313,17 @@ export default class ForceLayout extends Component {
|
||||
// console.log(item.get('model').style);
|
||||
// item.get('model').style = {fill: "black"};
|
||||
// 获取连线起点和终点坐标的对象后调用函数
|
||||
const edge = evt.item;
|
||||
const edge: IEdge = evt.item as IEdge;
|
||||
console.log(edge.getSource().getModel().name);
|
||||
console.log(edge.getSource().getModel());
|
||||
console.log(edge.getTarget().getModel().name);
|
||||
console.log(edge.getTarget().getModel());
|
||||
var temp = getCubicController (edge.getSource().getModel(), edge.getTarget().getModel());
|
||||
var temp = getCubicController(edge.getSource().getModel(), edge.getTarget().getModel());
|
||||
console.log(temp);
|
||||
})
|
||||
|
||||
function circleFun () {
|
||||
graph.updateLayout({type: 'circular', preventOverlap: true, radius: 200});
|
||||
function circleFun() {
|
||||
graph.updateLayout({ type: 'circular', preventOverlap: true, radius: 200 });
|
||||
document.getElementById('radial').style.backgroundColor = '#e2e2e2';
|
||||
document.getElementById('bigraph').style.backgroundColor = '#e2e2e2';
|
||||
document.getElementById('grid').style.backgroundColor = '#e2e2e2';
|
||||
@ -1333,8 +1334,8 @@ export default class ForceLayout extends Component {
|
||||
document.getElementById('dagre').style.backgroundColor = '#e2e2e2 ';
|
||||
document.getElementById('rect').style.backgroundColor = '#e2e2e2';
|
||||
}
|
||||
function radialFun () {
|
||||
graph.updateLayout({type: 'radial', preventOverlap: true, nodeSize: 203, strictRadial: true, linkDistance: 50, nodeSpacing: 30});
|
||||
function radialFun() {
|
||||
graph.updateLayout({ type: 'radial', preventOverlap: true, nodeSize: 203, strictRadial: true, linkDistance: 50, nodeSpacing: 30 });
|
||||
document.getElementById('circular').style.backgroundColor = '#e2e2e2 ';
|
||||
document.getElementById('bigraph').style.backgroundColor = '#e2e2e2';
|
||||
document.getElementById('grid').style.backgroundColor = '#e2e2e2';
|
||||
@ -1345,8 +1346,8 @@ export default class ForceLayout extends Component {
|
||||
document.getElementById('dagre').style.backgroundColor = '#e2e2e2 ';
|
||||
document.getElementById('rect').style.backgroundColor = '#e2e2e2';
|
||||
}
|
||||
function bigraphFun () {
|
||||
graph.updateLayout({type: 'bigraph-layout'});
|
||||
function bigraphFun() {
|
||||
graph.updateLayout({ type: 'bigraph-layout' });
|
||||
document.getElementById('radial').style.backgroundColor = '#e2e2e2';
|
||||
document.getElementById('grid').style.backgroundColor = '#e2e2e2';
|
||||
document.getElementById('circular').style.backgroundColor = '#e2e2e2 ';
|
||||
@ -1357,7 +1358,7 @@ export default class ForceLayout extends Component {
|
||||
document.getElementById('dagre').style.backgroundColor = '#e2e2e2 ';
|
||||
document.getElementById('rect').style.backgroundColor = '#e2e2e2';
|
||||
}
|
||||
function gridFun () {
|
||||
function gridFun() {
|
||||
graph.updateLayout({
|
||||
type: 'grid',
|
||||
begin: [20, 20],
|
||||
@ -1378,7 +1379,7 @@ export default class ForceLayout extends Component {
|
||||
document.getElementById('dagre').style.backgroundColor = '#e2e2e2 ';
|
||||
document.getElementById('rect').style.backgroundColor = '#e2e2e2';
|
||||
}
|
||||
function fruchtermanFun () {
|
||||
function fruchtermanFun() {
|
||||
graph.updateLayout({
|
||||
type: 'fruchterman',
|
||||
gravity: 5,
|
||||
@ -1394,7 +1395,7 @@ export default class ForceLayout extends Component {
|
||||
document.getElementById('dagre').style.backgroundColor = '#e2e2e2 ';
|
||||
document.getElementById('rect').style.backgroundColor = '#e2e2e2';
|
||||
}
|
||||
function concentricFun () {
|
||||
function concentricFun() {
|
||||
graph.updateLayout({
|
||||
type: 'concentric',
|
||||
preventOverlap: true,
|
||||
@ -1411,7 +1412,7 @@ export default class ForceLayout extends Component {
|
||||
document.getElementById('dagre').style.backgroundColor = '#e2e2e2 ';
|
||||
document.getElementById('rect').style.backgroundColor = '#e2e2e2';
|
||||
}
|
||||
function MDSFun () {
|
||||
function MDSFun() {
|
||||
graph.updateLayout({
|
||||
type: 'mds',
|
||||
linkDistance: 200
|
||||
@ -1426,7 +1427,7 @@ export default class ForceLayout extends Component {
|
||||
document.getElementById('dagre').style.backgroundColor = '#e2e2e2 ';
|
||||
document.getElementById('rect').style.backgroundColor = '#e2e2e2';
|
||||
}
|
||||
function DagreFun () {
|
||||
function DagreFun() {
|
||||
graph.updateLayout({
|
||||
type: 'dagre',
|
||||
rankdir: 'LR',
|
||||
@ -1445,8 +1446,8 @@ export default class ForceLayout extends Component {
|
||||
document.getElementById('dagre').style.backgroundColor = '#99FFFF ';
|
||||
document.getElementById('rect').style.backgroundColor = '#e2e2e2';
|
||||
}
|
||||
function rectFun () {
|
||||
graph.updateLayout({type: 'rect-layout'});
|
||||
function rectFun() {
|
||||
graph.updateLayout({ type: 'rect-layout' });
|
||||
document.getElementById('radial').style.backgroundColor = '#e2e2e2';
|
||||
document.getElementById('grid').style.backgroundColor = '#e2e2e2';
|
||||
document.getElementById('circular').style.backgroundColor = '#e2e2e2 ';
|
||||
@ -1457,36 +1458,36 @@ export default class ForceLayout extends Component {
|
||||
document.getElementById('dagre').style.backgroundColor = '#e2e2e2 ';
|
||||
document.getElementById('rect').style.backgroundColor = '#99FFFF';
|
||||
}
|
||||
function getCubicController (source, target) {
|
||||
function getCubicController(source, target) {
|
||||
let c1, c2;
|
||||
|
||||
let distance = (target.y - source.y)/5;
|
||||
if( distance > 0 ) distance = Math.max(distance, 80);
|
||||
if( distance < 0 ) distance = Math.min(distance, -80);
|
||||
let distance = (target.y - source.y) / 5;
|
||||
if (distance > 0) distance = Math.max(distance, 80);
|
||||
if (distance < 0) distance = Math.min(distance, -80);
|
||||
|
||||
let p1 = [
|
||||
source.x,
|
||||
source.y
|
||||
source.y
|
||||
];
|
||||
|
||||
let p4 = [
|
||||
target.x,
|
||||
target.y
|
||||
target.x,
|
||||
target.y
|
||||
]
|
||||
|
||||
if( target.y > source.y ) {
|
||||
c1 = [ source.x, source.y + distance ];
|
||||
c2 = [ target.x, target.y - distance ];
|
||||
if (target.y > source.y) {
|
||||
c1 = [source.x, source.y + distance];
|
||||
c2 = [target.x, target.y - distance];
|
||||
}
|
||||
else {
|
||||
c1 = [ source.x, source.y - distance ];
|
||||
c2 = [ target.x, target.y + distance ];
|
||||
c1 = [source.x, source.y - distance];
|
||||
c2 = [target.x, target.y + distance];
|
||||
}
|
||||
return {
|
||||
c1,
|
||||
c2
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,8 @@ let graph: IGraph = null;
|
||||
|
||||
const data = {
|
||||
nodes: [{
|
||||
id: '1'
|
||||
id: '1',
|
||||
comboId: 'c1'
|
||||
}, {
|
||||
id: '2'
|
||||
},],
|
||||
@ -14,6 +15,11 @@ const data = {
|
||||
source: '1',
|
||||
target: '2'
|
||||
}],
|
||||
combos: [{
|
||||
id: 'c1'
|
||||
}, {
|
||||
id: 'c2'
|
||||
}]
|
||||
};
|
||||
const data2 = {
|
||||
nodes: [{
|
||||
@ -35,7 +41,14 @@ const ToolBar = () => {
|
||||
const container = React.useRef();
|
||||
useEffect(() => {
|
||||
if (!graph) {
|
||||
const toolbar = new G6.ToolBar();
|
||||
const toolbarDiv = document.createElement('div');
|
||||
toolbarDiv.id = 'toolbarContainer';
|
||||
const graphContainer = container.current as HTMLElement;
|
||||
graphContainer.parentElement.appendChild(toolbarDiv);
|
||||
|
||||
const toolbar = new G6.ToolBar({
|
||||
container: 'toolbarContainer'
|
||||
});
|
||||
graph = new Graph({
|
||||
container: container.current as string | HTMLElement,
|
||||
width: 500,
|
||||
@ -44,7 +57,7 @@ const ToolBar = () => {
|
||||
// 设置为true,启用 redo & undo 栈功能
|
||||
enabledStack: true,
|
||||
modes: {
|
||||
default: ['zoom-canvas', 'drag-node', { type: 'brush-select', }],
|
||||
default: ['zoom-canvas', 'drag-node', { type: 'brush-select', }, 'drag-combo'],
|
||||
},
|
||||
defaultNode: {
|
||||
size: 50
|
||||
|
@ -28,8 +28,8 @@ interface IFlowCharts {
|
||||
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;
|
||||
handleEdgeHover?: (item: IEdge, graph: IGraph) => void;
|
||||
handleEdgeUnHover?: (item: IEdge, graph: IGraph) => void;
|
||||
collapseExpand?: boolean;
|
||||
}
|
||||
|
||||
@ -375,7 +375,7 @@ const FlowComponent: React.SFC<IFlowCharts> = ({
|
||||
}
|
||||
|
||||
graph.on('node:mouseenter', (evt) => {
|
||||
const { item } = evt;
|
||||
const item: INode = evt.item as INode;
|
||||
graph.setItemState(item, 'hover', true);
|
||||
if (handleNodeHover) {
|
||||
handleNodeHover(item, graph);
|
||||
@ -383,7 +383,7 @@ const FlowComponent: React.SFC<IFlowCharts> = ({
|
||||
});
|
||||
|
||||
graph.on('node:mouseleave', (evt) => {
|
||||
const { item } = evt;
|
||||
const item: INode = evt.item as INode;
|
||||
graph.setItemState(item, 'hover', false);
|
||||
if (handleNodeUnHover) {
|
||||
handleNodeUnHover(item, graph);
|
||||
@ -391,20 +391,21 @@ const FlowComponent: React.SFC<IFlowCharts> = ({
|
||||
});
|
||||
|
||||
graph.on('node:click', (evt) => {
|
||||
const { item, target } = evt;
|
||||
const item: INode = evt.item as INode;
|
||||
const { target } = evt;
|
||||
const targetType = target.get('type');
|
||||
const name = target.get('name');
|
||||
|
||||
// 增加元素
|
||||
if (targetType === 'marker') {
|
||||
const model = item.getModel();
|
||||
const model: TreeGraphData = item.getModel() as TreeGraphData;
|
||||
if (name === 'add-item') {
|
||||
if (!model.children) {
|
||||
model.children = [];
|
||||
}
|
||||
model.children.push({
|
||||
id: Math.random(),
|
||||
label: Math.random(),
|
||||
id: `${Math.random()}`,
|
||||
label: `${Math.random()}`
|
||||
});
|
||||
graph.updateChild(model, model.id);
|
||||
} else if (name === 'remove-item') {
|
||||
@ -418,7 +419,7 @@ const FlowComponent: React.SFC<IFlowCharts> = ({
|
||||
});
|
||||
|
||||
graph.on('edge:mouseenter', (evt) => {
|
||||
const { item } = evt;
|
||||
const item: IEdge = evt.item as IEdge;
|
||||
graph.setItemState(item, 'hover', true);
|
||||
if (handleEdgeHover) {
|
||||
handleEdgeHover(item, graph);
|
||||
@ -426,7 +427,7 @@ const FlowComponent: React.SFC<IFlowCharts> = ({
|
||||
});
|
||||
|
||||
graph.on('edge:mouseleave', (evt) => {
|
||||
const { item } = evt;
|
||||
const item: IEdge = evt.item as IEdge;
|
||||
graph.setItemState(item, 'hover', false);
|
||||
if (handleEdgeUnHover) {
|
||||
handleEdgeUnHover(item, graph);
|
||||
@ -434,7 +435,7 @@ const FlowComponent: React.SFC<IFlowCharts> = ({
|
||||
});
|
||||
|
||||
graph.on('edge:click', (evt) => {
|
||||
const { item } = evt;
|
||||
const item: IEdge = evt.item as IEdge;
|
||||
if (handleEdgeClick) {
|
||||
handleEdgeClick(item, graph);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user