Skip to content

Commit

Permalink
perf: optimize behaviors (#6465)
Browse files Browse the repository at this point in the history
* refactor: graph add rendered flag, setState add stage param

* perf: skip update transform when position doesnot change

* perf: optimize behaviors perf

---------

Co-authored-by: antv <[email protected]>
  • Loading branch information
Aarebecca and antv authored Nov 5, 2024
1 parent d912097 commit 49ba7ff
Show file tree
Hide file tree
Showing 9 changed files with 400 additions and 330 deletions.
4 changes: 3 additions & 1 deletion packages/g6/__tests__/demos/case-unicorns-investors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { Graph } from '@/src';
* 1086 nodes, 1247 edges
*
* 10 VC firms in Silicon Valley funded 82% of all unicorns, 98% of all exited unicorns. Data from CB Insights, updated March 2020.
* @param context
* @param context - context
* @returns - graph
*/
export const caseUnicornsInvestors: TestCase = async (context) => {
const data = await fetch('https://assets.antv.antgroup.com/g6/unicorns-investors.json').then((res) => res.json());
Expand Down Expand Up @@ -55,6 +56,7 @@ export const caseUnicornsInvestors: TestCase = async (context) => {
collide: { radius: (node: NodeData) => size(node) },
manyBody: { strength: (node: NodeData) => -4 * size(node) },
animation: false,
iterations: 20,
},
transforms: [
{
Expand Down
300 changes: 150 additions & 150 deletions packages/g6/__tests__/snapshots/behaviors/auto-adapt-label/padding-60.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
300 changes: 150 additions & 150 deletions packages/g6/__tests__/snapshots/behaviors/auto-adapt-label/zoom-3.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
55 changes: 43 additions & 12 deletions packages/g6/src/behaviors/auto-adapt-label.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,18 +125,24 @@ export class AutoAdaptLabel extends BaseBehavior<AutoAdaptLabelOptions> {
return res;
};

private get labelElements(): Record<ID, Element> {
private getLabelElements(): Element[] {
// @ts-expect-error access private property
const elements = Object.values(this.context.element.elementMap);
const labelElements = elements.filter((el: Element) => el.isVisible() && el.getShape('label'));
return Object.fromEntries(labelElements.map((el) => [el.id, el]));
const { elementMap } = this.context.element;
const elements: Element[] = [];

for (const key in elementMap) {
const element = elementMap[key];
if (element.isVisible() && element.getShape('label')) {
elements.push(element);
}
}

return elements;
}

private getLabelElementsInView(): Element[] {
const viewport = this.context.viewport!;
return Object.values(this.labelElements).filter((node) =>
viewport.isInViewport(node.getShape('key').getRenderBounds()),
);
return this.getLabelElements().filter((node) => viewport.isInViewport(node.getShape('key').getRenderBounds()));
}

private hideLabelIfExceedViewport = (prevElementsInView: Element[], currentElementsInView: Element[]) => {
Expand Down Expand Up @@ -186,7 +192,12 @@ export class AutoAdaptLabel extends BaseBehavior<AutoAdaptLabelOptions> {

private labelElementsInView: Element[] = [];

private isFirstRender = true;

protected onToggleVisibility = (event: IEvent) => {
// @ts-expect-error missing type
if (event.data?.stage === 'zIndex') return;

if (!this.validate(event)) {
if (this.hiddenElements.size > 0) {
this.hiddenElements.forEach(this.showLabel);
Expand All @@ -195,7 +206,7 @@ export class AutoAdaptLabel extends BaseBehavior<AutoAdaptLabelOptions> {
return;
}

const labelElementsInView = this.getLabelElementsInView();
const labelElementsInView = this.isFirstRender ? this.getLabelElements() : this.getLabelElementsInView();
this.hideLabelIfExceedViewport(this.labelElementsInView, labelElementsInView);
this.labelElementsInView = labelElementsInView;

Expand Down Expand Up @@ -227,17 +238,37 @@ export class AutoAdaptLabel extends BaseBehavior<AutoAdaptLabelOptions> {

protected onTransform = throttle(this.onToggleVisibility, this.options.throttle, { leading: true }) as () => void;

private enableToggle = true;

private toggle = (event: IEvent) => {
if (!this.enableToggle) return;
this.onToggleVisibility(event);
};

private onBeforeRender = () => {
this.enableToggle = false;
};

private onAfterRender = (event: IEvent) => {
this.onToggleVisibility(event);
this.enableToggle = true;
};

private bindEvents() {
const { graph } = this.context;
graph.on(GraphEvent.AFTER_DRAW, this.onToggleVisibility);
graph.on(GraphEvent.AFTER_LAYOUT, this.onToggleVisibility);
graph.on(GraphEvent.BEFORE_RENDER, this.onBeforeRender);
graph.on(GraphEvent.AFTER_RENDER, this.onAfterRender);
graph.on(GraphEvent.AFTER_DRAW, this.toggle);
graph.on(GraphEvent.AFTER_LAYOUT, this.toggle);
graph.on(GraphEvent.AFTER_TRANSFORM, this.onTransform);
}

private unbindEvents() {
const { graph } = this.context;
graph.off(GraphEvent.AFTER_DRAW, this.onToggleVisibility);
graph.off(GraphEvent.AFTER_LAYOUT, this.onToggleVisibility);
graph.off(GraphEvent.BEFORE_RENDER, this.onBeforeRender);
graph.off(GraphEvent.AFTER_RENDER, this.onAfterRender);
graph.off(GraphEvent.AFTER_DRAW, this.toggle);
graph.off(GraphEvent.AFTER_LAYOUT, this.toggle);
graph.off(GraphEvent.AFTER_TRANSFORM, this.onTransform);
}

Expand Down
17 changes: 15 additions & 2 deletions packages/g6/src/behaviors/fix-element-size.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,17 @@ import { isEmpty, isFunction, isNumber } from '@antv/util';
import { GraphEvent } from '../constants';
import type { RuntimeContext } from '../runtime/types';
import type { ComboData, EdgeData, NodeData } from '../spec';
import type { Combo, Edge, Element, ID, IViewportEvent, Node, NodeLikeData, State } from '../types';
import type {
Combo,
Edge,
Element,
ID,
IGraphLifeCycleEvent,
IViewportEvent,
Node,
NodeLikeData,
State,
} from '../types';
import { idOf } from '../utils/id';
import { getDescendantShapes } from '../utils/shape';
import type { BaseBehaviorOptions } from './base-behavior';
Expand Down Expand Up @@ -286,7 +296,10 @@ export class FixElementSize extends BaseBehavior<FixElementSizeOptions> {
// this.cachedStyles.clear();
}

private resetTransform = async () => {
private resetTransform = async (event: IGraphLifeCycleEvent) => {
// 首屏渲染时跳过 | Skip when rendering the first screen
if (event.data?.firstRender) return;

if (this.options.reset) {
this.restoreCachedStyles();
} else {
Expand Down
3 changes: 2 additions & 1 deletion packages/g6/src/elements/shapes/base-shape.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ export abstract class BaseShape<StyleProps extends BaseShapeStyleProps> extends
// Use `transform: translate3d()` instead of `x/y/z`
if ('x' in attributes || 'y' in attributes || 'z' in attributes) {
const { x = 0, y = 0, z = 0, transform } = attributes as any;
this.style.transform = replaceTranslateInTransform(+x, +y, +z, transform);
const newTransform = replaceTranslateInTransform(+x, +y, +z, transform);
if (newTransform) this.style.transform = newTransform;
}
}

Expand Down
22 changes: 15 additions & 7 deletions packages/g6/src/runtime/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,28 +278,30 @@ export class ElementController {
const data = this.computeChangesAndDrawData(context);
if (!data) return null;

const { type = 'draw', stage = type, animation, silence } = context;
const { dataChanges, drawData } = data;
this.markDestroyElement(drawData);
// 计算样式 / Calculate style
this.computeStyle(context.stage);
this.computeStyle(stage);
// 创建渲染任务 / Create render task
const { add, update, remove } = drawData;
this.destroyElements(remove, context);
this.createElements(add, context);
this.updateElements(update, context);

const { animation, silence } = context;

const { type = 'draw' } = context;

return this.context.animation!.animate(
animation,
silence
? {}
: {
before: () =>
this.emit(
new GraphLifeCycleEvent(GraphEvent.BEFORE_DRAW, { dataChanges, animation, render: type === 'render' }),
new GraphLifeCycleEvent(GraphEvent.BEFORE_DRAW, {
dataChanges,
animation,
stage,
render: type === 'render',
}),
context,
),
beforeAnimate: (animation) =>
Expand All @@ -308,7 +310,13 @@ export class ElementController {
this.emit(new AnimateEvent(GraphEvent.AFTER_ANIMATE, AnimationType.DRAW, animation, drawData), context),
after: () =>
this.emit(
new GraphLifeCycleEvent(GraphEvent.AFTER_DRAW, { dataChanges, animation, render: type === 'render' }),
new GraphLifeCycleEvent(GraphEvent.AFTER_DRAW, {
dataChanges,
animation,
stage,
render: type === 'render',
firstRender: this.context.graph.rendered === false,
}),
context,
),
},
Expand Down
10 changes: 9 additions & 1 deletion packages/g6/src/runtime/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ export class Graph extends EventEmitter {
zoomRange: [0.01, 10],
};

/**
* <zh/> 当前图实例是否已经渲染
*
* <en/> Whether the current graph instance has been rendered
*/
public rendered = false;

/**
* <zh/> 当前图实例是否已经被销毁
*
Expand Down Expand Up @@ -1125,6 +1132,7 @@ export class Graph extends EventEmitter {
const animation = this.context.element!.draw({ type: 'render' });
await Promise.all([animation?.finished, this.context.layout!.layout()]);
await this.autoFit();
this.rendered = true;
emit(this, new GraphLifeCycleEvent(GraphEvent.AFTER_RENDER));
}

Expand Down Expand Up @@ -1744,7 +1752,7 @@ export class Graph extends EventEmitter {
});
this.updateData(dataToUpdate);

await this.context.element!.draw({ animation })?.finished;
await this.context.element!.draw({ animation, stage: 'state' })?.finished;
}

/**
Expand Down
19 changes: 13 additions & 6 deletions packages/g6/src/utils/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,26 @@ export function replaceTranslateInTransform(
y: number,
z: number,
transform: string | TransformArray,
): string | TransformArray {
): string | TransformArray | null {
if (Array.isArray(transform)) {
let hasTranslate = false;
const newTransform: TransformArray = transform.map((t) => {
const newTransform: TransformArray = [];

for (let i = 0; i < transform.length; i++) {
const t = transform[i];
if (t[0] === 'translate') {
if (t[1] === x && t[2] === y) return null;
hasTranslate = true;
return ['translate', x, y];
newTransform.push(['translate', x, y]);
} else if (t[0] === 'translate3d') {
if (t[1] === x && t[2] === y && t[3] === z) return null;
hasTranslate = true;
return ['translate3d', x, y, z];
newTransform.push(['translate3d', x, y, z]);
} else {
newTransform.push(t);
}
return t;
});
}

if (!hasTranslate) {
newTransform.splice(0, 0, z === 0 ? ['translate', x, y] : ['translate3d', x, y, z]);
}
Expand Down

0 comments on commit 49ba7ff

Please sign in to comment.