diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f61eb8d9b3..c9d2cf22658 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # ChangeLog +#### 4.6.18 + +- feat: updateLayout from no pipes to pipes, closes: #3726; +- fix: relayout with pipes; + #### 4.6.17 - fix: legend changeData problem, closes: #3561; diff --git a/packages/core/src/graph/controller/layout.ts b/packages/core/src/graph/controller/layout.ts index 08cb106bc23..5c43905ac14 100644 --- a/packages/core/src/graph/controller/layout.ts +++ b/packages/core/src/graph/controller/layout.ts @@ -50,11 +50,17 @@ export default abstract class LayoutController { protected isLayoutTypeSame(cfg): boolean { const current = this.getLayoutCfgType(cfg); - // already has pipes - if (Array.isArray(this.layoutType)) { - return this.layoutType.every((type, index) => type === current[index]); + const preHasPipies = Array.isArray(this.layoutType); + const currentHasPipes = Array.isArray(current); + // already has pipes, and the new one is pipes + if (preHasPipies && currentHasPipes) { + return (this.layoutType as string[]).every((type, index) => type === current[index]); } - + // only one of the pre and current is pipes + if (Array.isArray(current) || Array.isArray(this.layoutType)) { + return false; + } + // both of the pre and current are not pipes return cfg?.type === this.layoutType; } @@ -171,28 +177,7 @@ export default abstract class LayoutController { } as GraphData; } - protected reLayoutMethod(layoutMethod, layoutCfg): Promise { - return new Promise((reslove, reject) => { - const { graph } = this; - const layoutType = layoutCfg?.type; - - // 每个布局方法都需要注册 - layoutCfg.onLayoutEnd = () => { - graph.emit('aftersublayout', { type: layoutType }); - reslove(); - }; - - layoutMethod.init(this.data); - if (layoutType === 'force') { - layoutMethod.ticking = false; - layoutMethod.forceSimulation.stop(); - } - - graph.emit('beforesublayout', { type: layoutType }); - layoutMethod.execute(); - if (layoutMethod.isCustomLayout && layoutCfg.onLayoutEnd) layoutCfg.onLayoutEnd(); - }); - } + protected abstract execLayoutMethod(layoutCfg, order): Promise; // 重新布局 public relayout(reloadData?: boolean) { @@ -213,7 +198,7 @@ export default abstract class LayoutController { layoutMethods?.forEach((layoutMethod: any, index: number) => { const currentCfg = layoutCfg[index] || layoutCfg; start = start.then(() => { - const relayoutPromise = this.reLayoutMethod(layoutMethod, currentCfg); + const relayoutPromise = this.execLayoutMethod(layoutMethod, currentCfg); if (index === layoutMethods.length - 1) { layoutCfg.onAllLayoutEnd?.(); } diff --git a/packages/core/src/graph/graph.ts b/packages/core/src/graph/graph.ts index 42b5ca54056..2506e502fa4 100644 --- a/packages/core/src/graph/graph.ts +++ b/packages/core/src/graph/graph.ts @@ -2484,10 +2484,11 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs const oriLayoutCfg = { ...this.get('layout') }; const layoutCfg: any = {}; Object.assign(layoutCfg, oriLayoutCfg, cfg); + if (cfg.pipes && !cfg.type) delete layoutCfg.type; + else if (!cfg.pipes && layoutCfg.type) delete layoutCfg.pipes; this.set('layout', layoutCfg); if (!layoutController) return; - if ( layoutController.isLayoutTypeSame(layoutCfg) && layoutCfg.gpuEnabled === oriLayoutCfg.gpuEnabled diff --git a/packages/pc/src/graph/controller/layout.ts b/packages/pc/src/graph/controller/layout.ts index 8061cbda6c4..4d0f47d81e7 100644 --- a/packages/pc/src/graph/controller/layout.ts +++ b/packages/pc/src/graph/controller/layout.ts @@ -106,7 +106,7 @@ export default class LayoutController extends AbstractLayout { } } - private execLayoutMethod(layoutCfg, order): Promise { + protected execLayoutMethod(layoutCfg, order): Promise { return new Promise(async (reslove, reject) => { const { graph } = this; if (!graph || graph.get('destroyed')) return; diff --git a/packages/site/docs/manual/middle/elements/nodes/jsx-node.en.md b/packages/site/docs/manual/middle/elements/nodes/jsx-node.en.md index 3eb7e1c0b0a..f6d6a189d72 100644 --- a/packages/site/docs/manual/middle/elements/nodes/jsx-node.en.md +++ b/packages/site/docs/manual/middle/elements/nodes/jsx-node.en.md @@ -79,6 +79,19 @@ G6.registerNode( Using JSX-like syntax to customize a complicated node. ```javascript +// Propose the data for a node as following: +const data = { + nodes: [ + { + id: 'node1', + type: 'xml-card', // the custom node's type name + metric: 'CPU usage', + cpuUsage: 80 + }, + ] +} + +// def for the drawing of the percentage bar const percentageBar = ({ width, used, height = 12 }) => ` ` `; +// def for the drawing of the jsx node const textXML = (cfg) => ` ` radius: [0, 0, 6, 6] }} keyshape="true" cursor="move"> - ${FULL} + ${FULL} ${cfg.metric}: ` `; +// register the custom node to G6 G6.registerNode('test', { jsx: textXML, }); diff --git a/packages/site/docs/manual/middle/elements/nodes/jsx-node.zh.md b/packages/site/docs/manual/middle/elements/nodes/jsx-node.zh.md index afb0ef79e4e..9c5773ed434 100644 --- a/packages/site/docs/manual/middle/elements/nodes/jsx-node.zh.md +++ b/packages/site/docs/manual/middle/elements/nodes/jsx-node.zh.md @@ -79,6 +79,19 @@ G6.registerNode( 我们再来看一个稍微复杂的案例。 ```javascript +// 假设一个节点数据如下: +const data = { + nodes: [ + { + id: 'node1', + type: 'xml-card', // 使用自定义的节点名称 + metric: 'CPU usage', + cpuUsage: 80 + }, + ] +} + +// 定义进度条的绘制方式 const percentageBar = ({ width, used, height = 12 }) => ` ` `; +// 定义节点的 jsx 绘制方式 const textXML = (cfg) => ` ` radius: [0, 0, 6, 6] }} keyshape="true" cursor="move"> - ${FULL} + 'FULL' ${cfg.metric}: ` `; -G6.registerNode('test', { +// 注册节点 +G6.registerNode('xml-card', { jsx: textXML, }); ```