Skip to content

Commit

Permalink
perf: skip unnecessary style copy of unnecessary and computing style
Browse files Browse the repository at this point in the history
  • Loading branch information
antv committed Sep 3, 2024
1 parent 36f3e54 commit 920ba80
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 17 deletions.
27 changes: 16 additions & 11 deletions packages/g6/src/runtime/animation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,22 +79,24 @@ export class Animation {
* @param options - <zh/> 扩展选项 | <en/> Extend options
* @returns <zh/> 始态样式与终态样式 | <en/> Initial style and final style
*/
public inferStyle(context: AnimationContext, options?: ExtendOptions) {
public inferStyle(
context: AnimationContext,
options?: ExtendOptions,
): [Record<string, unknown>, Record<string, unknown>] {
const { element, elementType, stage, originalStyle, modifiedStyle } = context;

const fromStyle = { ...originalStyle };
const toStyle = { ...modifiedStyle };
const getCacheOpacity = () => getCachedStyle(element, 'opacity') ?? inferDefaultValue('opacity');
const fromStyle: Record<string, unknown> = {};
const toStyle: Record<string, unknown> = {};

if (stage === 'enter') {
Object.assign(fromStyle, { opacity: 0 });
} else if (stage === 'exit') {
Object.assign(toStyle, { opacity: 0 });
} else if (stage === 'show') {
Object.assign(fromStyle, { opacity: 0 });
Object.assign(toStyle, { opacity: getCacheOpacity() });
Object.assign(toStyle, { opacity: getCachedStyle(element, 'opacity') ?? inferDefaultValue('opacity') });
} else if (stage === 'hide') {
Object.assign(fromStyle, { opacity: getCacheOpacity() });
Object.assign(fromStyle, { opacity: getCachedStyle(element, 'opacity') ?? inferDefaultValue('opacity') });
Object.assign(toStyle, { opacity: 0 });
} else if (stage === 'collapse') {
const { collapse } = options || {};
Expand All @@ -109,10 +111,10 @@ export class Animation {
} else if (elementType === 'combo') {
if (element.id === target || descendants.includes(element.id)) {
const [x, y] = position;
Object.assign(toStyle, { x, y, childrenNode: fromStyle.childrenNode });
Object.assign(toStyle, { x, y, childrenNode: originalStyle.childrenNode });
}
} else if (elementType === 'edge') {
Object.assign(toStyle, { sourceNode: fromStyle.sourceNode, targetNode: fromStyle.targetNode });
Object.assign(toStyle, { sourceNode: modifiedStyle.sourceNode, targetNode: modifiedStyle.targetNode });
}
} else if (stage === 'expand') {
const { expand } = options || {};
Expand All @@ -129,16 +131,19 @@ export class Animation {
// Set the child elements of the expanded combo
if (element.id === target || descendants.includes(element.id)) {
const [x, y, z] = position;
Object.assign(fromStyle, { x, y, z, childrenNode: toStyle.childrenNode });
Object.assign(fromStyle, { x, y, z, childrenNode: modifiedStyle.childrenNode });
}
} else if (elementType === 'edge') {
// 设置展开后的边的起点和终点
// Set the starting point and end point of the edge after expansion
Object.assign(fromStyle, { sourceNode: toStyle.sourceNode, targetNode: toStyle.targetNode });
Object.assign(fromStyle, { sourceNode: modifiedStyle.sourceNode, targetNode: modifiedStyle.targetNode });
}
}

return [fromStyle, toStyle] as [Record<string, unknown>, Record<string, unknown>];
return [
Object.keys(fromStyle).length > 0 ? Object.assign({}, originalStyle, fromStyle) : originalStyle,
Object.keys(toStyle).length > 0 ? Object.assign({}, modifiedStyle, toStyle) : modifiedStyle,
];
}

public stop() {
Expand Down
26 changes: 20 additions & 6 deletions packages/g6/src/runtime/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import type {
ElementType,
ID,
Node,
NodeLikeData,
State,
StyleIterationContext,
} from '../types';
Expand Down Expand Up @@ -287,7 +288,6 @@ export class ElementController {
const { animation, silence } = context;

const { type = 'draw' } = context;
const willRender = type === 'render';

return this.context.animation!.animate(
animation,
Expand All @@ -296,7 +296,7 @@ export class ElementController {
: {
before: () =>
this.emit(
new GraphLifeCycleEvent(GraphEvent.BEFORE_DRAW, { dataChanges, animation, render: willRender }),
new GraphLifeCycleEvent(GraphEvent.BEFORE_DRAW, { dataChanges, animation, render: type === 'render' }),
context,
),
beforeAnimate: (animation) =>
Expand All @@ -305,7 +305,7 @@ 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: willRender }),
new GraphLifeCycleEvent(GraphEvent.AFTER_DRAW, { dataChanges, animation, render: type === 'render' }),
context,
),
},
Expand Down Expand Up @@ -433,16 +433,32 @@ export class ElementController {
});
}

private getUpdateStageStyle(elementType: ElementType, datum: ElementDatum, context: DrawContext) {
const { stage = 'update' } = context;

// 优化 translate 阶段,直接返回 x, y, z,避免计算样式
// Optimize the translate stage, return x, y, z directly to avoid calculating style
if (stage === 'translate') {
if (elementType === 'node' || elementType === 'combo') {
const { style: { x = 0, y = 0, z = 0 } = {} } = datum as NodeLikeData;
return { x, y, z };
} else return {};
}

return this.getElementComputedStyle(elementType, datum);
}

private updateElement(elementType: ElementType, datum: ElementDatum, context: DrawContext) {
const id = idOf(datum);
const { stage = 'update' } = context;

const element = this.getElement(id);
if (!element) return () => null;

this.emit(new ElementLifeCycleEvent(GraphEvent.BEFORE_ELEMENT_UPDATE, elementType, datum), context);

const type = this.getElementType(elementType, datum);
const style = this.getElementComputedStyle(elementType, datum);
const style = this.getUpdateStageStyle(elementType, datum, context);

// 如果类型不同,需要先销毁原有元素,再创建新元素
// If the type is different, you need to destroy the original element first, and then create a new element
Expand All @@ -454,8 +470,6 @@ export class ElementController {
this.createElement(elementType, datum, { animation: false, silence: true });
}

const { stage = 'update' } = context;

const exactStage = stage !== 'visibility' ? stage : style.visibility === 'hidden' ? 'hide' : 'show';

// 避免立即将 visibility 设置为 hidden,导致元素不可见,而是在 after 阶段再设置
Expand Down

0 comments on commit 920ba80

Please sign in to comment.