Skip to content

Commit

Permalink
chore: upgrade version num (#4036)
Browse files Browse the repository at this point in the history
* chore: upgrade version num

* Fix combos to inherit animation setting from graph (#3992)

* fix: createCombo didn't update the "comboTrees" correctly (#3993)

* Fix the comboTrees update in createCombo()

* Copy tests from core to pc

* Fix useless conditional

* Change variable name to not include verb

* Add some missing types

* docs: update traverseTree and traverseTreeUp doc

* fix: drag-canvas incorrectly stopped by right click; perf: improve the performance of setItemState and active-relations again;

* fix: setItemState on node, related edges linking positions are not refreshed; feat: graph supports optimizeThreshold to control the number threshold of nodes to enable the optimization on rendering and interaction, currently only affects the edges refresh while the related node state style changed;

* chore: update CHANGELOG

* chore: tests refine

* docs: update docs and demos for force2 on website

Co-authored-by: daniele-pini <[email protected]>
  • Loading branch information
Yanyan-Wang and daniele-pini authored Nov 9, 2022
1 parent 1ff0e54 commit 76da663
Show file tree
Hide file tree
Showing 43 changed files with 1,631 additions and 265 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# ChangeLog

### 4.7.12

- fix: drag-canvas incorrectly stopped by right click;
- fix: createCombo with nodes which already has parent combos;
- fix: setItemState on node, related edges's linking positions are not refreshed;
- perf: combo animate inherit from graph's animate config;
- perf: improve the performance of setItemState and active-relations again;
- feat: graph supports optimizeThreshold to control the number threshold of nodes to enable the optimization on rendering and interaction, currently only affects the edges' refresh while the related node state style changed;

### 4.7.11

- perf: improve the performance of setItemState and active-relations;
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@antv/g6-core",
"version": "0.7.11",
"version": "0.7.12",
"description": "A Graph Visualization Framework in JavaScript",
"keywords": [
"antv",
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const colorSet = {
};

export default {
version: '0.7.11',
version: '0.7.12',
rootContainerClassName: 'root-container',
nodeContainerClassName: 'node-container',
edgeContainerClassName: 'edge-container',
Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/graph/controller/item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ export default class ItemController {
item = new Combo({
model,
styles,
animate: false,
animate: graph.get('animate'),
bbox: model.collapsed ? getComboBBox([], graph) : comboBBox,
group: comboGroup,
});
Expand All @@ -186,6 +186,7 @@ export default class ItemController {
}

if (item) {
item.setOptimize(graph.getNodes().length > graph.get('optimizeThreshold'));
graph.get(`${type}s`).push(item);
graph.get('itemMap')[item.get('id')] = item;
graph.emit('afteradditem', { item, model });
Expand Down Expand Up @@ -318,6 +319,7 @@ export default class ItemController {
}
}
}
item.setOptimize(graph.getNodes().length > graph.get('optimizeThreshold'));
graph.emit('afterupdateitem', { item, cfg });
}
/**
Expand Down
77 changes: 61 additions & 16 deletions packages/core/src/graph/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
floydWarshall,
} from '@antv/algorithm';
import { IAbstractGraph } from '../interface/graph';
import { IEdge, INode, ICombo, IItemBaseConfig } from '../interface/item';
import { IEdge, INode, ICombo } from '../interface/item';
import {
GraphAnimateConfig,
GraphOptions,
Expand Down Expand Up @@ -340,6 +340,9 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs

// 存储图上的 tooltip dom,方便销毁
tooltips: [],

// 达到这一节点数量(默认值 1000),将开启性能优化模式。目前包括:节点状态样式变更是否影响相关边的更新
optimizeThreshold: 1000
};
}

Expand Down Expand Up @@ -1748,6 +1751,8 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs
* @param children 添加到 Combo 中的元素,包括节点和 combo
*/
public createCombo(combo: string | ComboConfig, children: string[]): void {
const itemController: ItemController = this.get('itemController');

this.set('comboSorted', false);
// step 1: 创建新的 Combo
let comboId = '';
Expand All @@ -1767,14 +1772,52 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs
comboConfig = combo;
}

// step2: 更新 children,根据类型添加 comboId 或 parentId
// step 2: Pull children out of their parents
let comboTrees = this.get('comboTrees');
const childrenIdsSet = new Set<string>(children);
const pulledComboTreesById = new Map<string, ComboTree>();

if (comboTrees) {
comboTrees.forEach(ctree => {
traverseTreeUp<ComboTree>(ctree, (treeNode, parentTreeNode, index) => {
if (childrenIdsSet.has(treeNode.id)) {
if (parentTreeNode) {
const parentItem = this.findById(parentTreeNode.id) as ICombo;
const item = this.findById(treeNode.id) as INode | ICombo;

// Removing current item from the tree during the traversal is ok because children traversal is done
// in an *inverse order* - indices of the next-traversed items are not disturbed by the removal.
parentTreeNode.children.splice(index, 1);
parentItem.removeChild(item);

// We have to update the parent node geometry since nodes were removed from them, _while they are still visible_
// (combos may be moved inside the new combo and become hidden)
itemController.updateCombo(parentItem, parentTreeNode.children);
}

if (treeNode.itemType === 'combo') {
pulledComboTreesById.set(treeNode.id, treeNode);
}
}

return true;
});
});
comboTrees = comboTrees.filter(ctree => !childrenIdsSet.has(ctree.id));

this.set('comboTrees', comboTrees);
}

// step 3: 更新 children,根据类型添加 comboId 或 parentId
const trees: ComboTree[] = children.map(elementId => {
const item = this.findById(elementId);
const model = item.getModel();

let type = '';
if (item.getType) type = item.getType();
const cItem: ComboTree = {

// Combos will be just moved around, so their children can be preserved
const cItem: ComboTree = pulledComboTreesById.get(elementId) || {
id: item.getID(),
itemType: type as 'node' | 'combo',
};
Expand All @@ -1792,23 +1835,25 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs

comboConfig.children = trees;

// step 3: 添加 Combo,addItem 时会将子将元素添加到 Combo 中
// step 4: 添加 Combo,addItem 时会将子将元素添加到 Combo 中
this.addItem('combo', comboConfig, false);
this.set('comboSorted', false);

// step4: 更新 comboTrees 结构
const comboTrees = this.get('comboTrees');
(comboTrees || []).forEach(ctree => {
traverseTreeUp<ComboTree>(ctree, child => {
if (child.id === comboId) {
child.itemType = 'combo';
child.children = trees as ComboTree[];
return false;
}
return true;
});
});
// step 5: 更新 comboTrees 结构
if (comboTrees) {
comboTrees.forEach(ctree => {
traverseTree<ComboTree>(ctree, (treeNode) => {
// Set the children to the newly created combo
if (treeNode.id === comboId) {
treeNode.itemType = 'combo';
treeNode.children = trees as ComboTree[];
return false;
}

return true;
});
});

this.sortCombos();
}
}
Expand Down
7 changes: 7 additions & 0 deletions packages/core/src/interface/item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,13 @@ export interface IItemBase {

getUpdateType: (cfg?: ModelConfig) => UpdateType;

/**
* 设置是否开启性能优化模式
* 目前影响:节点的状态样式更新是否影响相关边的更新
* @param {Boolean} enableOptimize 是否开启
*/
setOptimize: (enableOptimize: boolean) => void;

get: <T = any>(key: string) => T;
set: <T = any>(key: string, value: T) => void;

Expand Down
12 changes: 12 additions & 0 deletions packages/core/src/item/item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ export default class ItemBase implements IItemBase {

public destroyed: boolean = false;

// 是否开启优化,由 graph 根据当前图上节点数量来控制
protected optimize: boolean = false;

constructor(cfg: IItemBaseConfig) {
const defaultCfg: IItemBaseConfig = {
/**
Expand Down Expand Up @@ -530,6 +533,15 @@ export default class ItemBase implements IItemBase {
});
}

/**
* 设置是否开启性能优化模式
* 目前影响:节点的状态样式更新是否影响相关边的更新
* @param {Boolean} enableOptimize 是否开启
*/
public setOptimize(enableOptimize: boolean) {
this.optimize = enableOptimize;
}

/**
* 节点的图形容器
* @return {G.Group} 图形容器
Expand Down
36 changes: 36 additions & 0 deletions packages/core/src/item/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,42 @@ export default class Node extends Item implements INode {
let updateLabel = keys.includes('label') || keys.includes('labelCfg');

return updateLabel ? 'style|label' : 'style';
}
public setState(state: string, value: string | boolean) {
if (this.optimize) {
super.setState(state, value);
return;
}
this.runWithBBoxAffected(() => super.setState(state, value));

}
public clearStates(states?: string | string[]) {
if (this.optimize) {
super.clearStates(states);
return;
}
this.runWithBBoxAffected(() => super.clearStates(states));
}

private runWithBBoxAffected(fn: Function) {
const bboxAffectedStyleKeys = ['r', 'width', 'height', 'rx', 'ry', 'lineWidth'];
const beforeAttrs = this.getKeyShape().attr();
const bboxAffectedStyleBefore = {};
Object.keys(this.getKeyShape().attr()).forEach(key => {
if (bboxAffectedStyleKeys.includes(key)) bboxAffectedStyleBefore[key] = beforeAttrs[key]
});

fn();

// if the state styles affect the bbox, the bbox cache should be cleared to get correct edge connecting points
const afterAttrs = this.getKeyShape().attr();
for (let i = 0; i < bboxAffectedStyleKeys.length; i++) {
const key = bboxAffectedStyleKeys[i];
if (afterAttrs[key] !== bboxAffectedStyleBefore[key]) {
this.clearCache();
this.getEdges().forEach(edge => edge.refresh());
break;
}
}
}
}
6 changes: 6 additions & 0 deletions packages/core/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,12 @@ export interface GraphOptions {
tooltips?: [];

pixelRatio?: number;

/**
* 达到这一节点数量,将开启性能优化模式
* 目前包括:节点状态样式变更是否影响相关边的更新
*/
optimizeThreshold?: number;
}

export type LabelStyle = Partial<{
Expand Down
35 changes: 24 additions & 11 deletions packages/core/src/util/graphic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,14 +344,19 @@ export const getLabelPosition = (
* depth first traverse, from root to leaves, children in inverse order
* if the fn returns false, terminate the traverse
*/
const traverse = <T extends { children?: T[] }>(data: T, fn: (param: T) => boolean) => {
if (fn(data) === false) {
const traverse = <T extends { children?: T[] }>(
data: T,
parent: T | null,
index: number,
fn: (data: T, parent: T | null, index: number) => boolean
) => {
if (fn(data, parent, index) === false) {
return false;
}

if (data && data.children) {
for (let i = data.children.length - 1; i >= 0; i--) {
if (!traverse(data.children[i], fn)) return false;
if (!traverse(data.children[i], data, i, fn)) return false;
}
}
return true;
Expand All @@ -361,14 +366,19 @@ const traverse = <T extends { children?: T[] }>(data: T, fn: (param: T) => boole
* depth first traverse, from leaves to root, children in inverse order
* if the fn returns false, terminate the traverse
*/
const traverseUp = <T extends { children?: T[] }>(data: T, fn: (param: T) => boolean) => {
const traverseUp = <T extends { children?: T[] }>(
data: T,
parent: T | null,
index: number,
fn: (data: T, parent: T | null, index: number) => boolean
) => {
if (data && data.children) {
for (let i = data.children.length - 1; i >= 0; i--) {
if (!traverseUp(data.children[i], fn)) return;
if (!traverseUp(data.children[i], data, i, fn)) return;
}
}

if (fn(data) === false) {
if (fn(data, parent, index) === false) {
return false;
}
return true;
Expand All @@ -378,11 +388,14 @@ const traverseUp = <T extends { children?: T[] }>(data: T, fn: (param: T) => boo
* depth first traverse, from root to leaves, children in inverse order
* if the fn returns false, terminate the traverse
*/
export const traverseTree = <T extends { children?: T[] }>(data: T, fn: (param: T) => boolean) => {
export const traverseTree = <T extends { children?: T[] }>(
data: T,
fn: (data: T, parent: T | null, index: number) => boolean
) => {
if (typeof fn !== 'function') {
return;
}
traverse(data, fn);
traverse(data, null, -1, fn);
};

/**
Expand All @@ -391,12 +404,12 @@ export const traverseTree = <T extends { children?: T[] }>(data: T, fn: (param:
*/
export const traverseTreeUp = <T extends { children?: T[] }>(
data: T,
fn: (param: T) => boolean,
fn: (data: T, parent: T | null, index: number) => boolean,
) => {
if (typeof fn !== 'function') {
return;
}
traverseUp(data, fn);
traverseUp(data, null, -1, fn);
};

/**
Expand Down Expand Up @@ -525,7 +538,7 @@ export const plainCombosToTrees = (array: ComboConfig[], nodes?: NodeConfig[]) =
let maxDepth = 0;
result.forEach((tree: ComboTree) => {
tree.depth = maxDepth + 10;
traverse<ComboTree>(tree, (child) => {
traverseTree<ComboTree>(tree, (child) => {
let parent;
const itemType = addedMap[child.id].itemType;
if (itemType === 'node') {
Expand Down
Loading

0 comments on commit 76da663

Please sign in to comment.