Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fix part of element lost when set visibility in animation #6197

Merged
merged 1 commit into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions packages/g6/__tests__/bugs/utils-set-visibility.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { createGraph } from '@@/utils';

describe('bug: utils-set-visibility', () => {
it('should set correct', async () => {
const graph = createGraph({
animation: true,
data: {
nodes: [
{
id: 'node-0',
style: {
x: 100,
y: 100,
labelText: 'label',
iconText: 'icon',
badges: [{ text: 'b1', placement: 'right-top' }],
},
},
],
},
});

await graph.render();

await expect(graph).toMatchSnapshot(__filename);

await graph.hideElement('node-0');

await expect(graph).toMatchSnapshot(__filename, 'hidden');

await graph.showElement('node-0');

await expect(graph).toMatchSnapshot(__filename, 'visible');
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions packages/g6/__tests__/unit/utils/visibility.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ describe('visibility', () => {
expect(vShape.style.visibility).toBe(undefined);
expect(hShape.style.visibility).toBe('hidden');

shape.update({ visibility: 'hidden' });
setVisibility(shape, 'hidden');
expect(shape.style.visibility).toBe('hidden');
expect(vShape.style.visibility).toBe('hidden');
expect(hShape.style.visibility).toBe('hidden');

shape.update({ visibility: 'visible' });
setVisibility(shape, 'visible');
expect(shape.style.visibility).toBe('visible');
expect(vShape.style.visibility).toBe('visible');
expect(hShape.style.visibility).toBe('hidden');
Expand All @@ -39,7 +39,7 @@ describe('visibility', () => {
expect(vShape.style.visibility).toBe('hidden');
expect(hShape.style.visibility).toBe('hidden');

shape.update({ visibility: 'visible' });
setVisibility(shape, 'visible');
expect(shape.style.visibility).toBe('visible');
expect(vShape.style.visibility).toBe('visible');
expect(hShape.style.visibility).toBe('hidden');
Expand Down
1 change: 1 addition & 0 deletions packages/g6/src/behaviors/optimize-viewport-transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export class OptimizeViewportTransform extends BaseBehavior<OptimizeViewportTran
setVisibility(
element,
visibility,
false,
(shape) => !!shape.className && !excludedClassnames?.includes(shape.className),
);
});
Expand Down
2 changes: 1 addition & 1 deletion packages/g6/src/elements/shapes/base-shape.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ export abstract class BaseShape<StyleProps extends BaseShapeStyleProps> extends

private setVisibility() {
const { visibility } = this.attributes;
setVisibility(this, visibility);
setVisibility(this, visibility, true);
}

public destroy(): void {
Expand Down
15 changes: 11 additions & 4 deletions packages/g6/src/runtime/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import type {
State,
StyleIterationContext,
} from '../types';
import { cacheStyle, getCachedStyle, hasCachedStyle, setCacheStyle } from '../utils/cache';
import { cacheStyle, hasCachedStyle } from '../utils/cache';
import { reduceDataChanges } from '../utils/change';
import { isCollapsed } from '../utils/collapsibility';
import { markToBeDestroyed, updateStyle } from '../utils/element';
Expand All @@ -34,6 +34,7 @@ import { positionOf } from '../utils/position';
import { print } from '../utils/print';
import { computeElementCallbackStyle } from '../utils/style';
import { themeOf } from '../utils/theme';
import { setVisibility } from '../utils/visibility';
import type { RuntimeContext } from './types';

export class ElementController {
Expand Down Expand Up @@ -451,6 +452,10 @@ export class ElementController {

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

// 避免立即将 visibility 设置为 hidden,导致元素不可见,而是在 after 阶段再设置
// Avoid setting visibility to hidden immediately, causing the element to be invisible, but set it in the after phase
if (exactStage === 'hide') delete style['visibility'];

this.context.animation?.add(
{
element,
Expand All @@ -470,14 +475,14 @@ export class ElementController {
// 缓存原始透明度 / Cache original opacity
// 会在 animation controller 中访问该缓存值 / The cached value will be accessed in the animation controller
if (!hasCachedStyle(element, 'opacity')) cacheStyle(element, 'opacity');
setCacheStyle(element, 'visibility', exactStage === 'show' ? 'visible' : 'hidden');
if (exactStage === 'show') updateStyle(element, { visibility: 'visible' });
this.visibilityCache.set(element, exactStage === 'show' ? 'visible' : 'hidden');
if (exactStage === 'show') setVisibility(element, 'visible');
}
},
after: () => {
const element = this.elementMap[id];
if (stage === 'collapse') updateStyle(element, style);
if (exactStage === 'hide') updateStyle(element, { visibility: getCachedStyle(element, 'visibility') });
if (exactStage === 'hide') setVisibility(element, this.visibilityCache.get(element));
this.emit(new ElementLifeCycleEvent(GraphEvent.AFTER_ELEMENT_UPDATE, elementType, datum), context);
element.onUpdate?.();
},
Expand All @@ -498,6 +503,8 @@ export class ElementController {
});
}

private visibilityCache = new WeakMap<Element, BaseStyleProps['visibility']>();

/**
* <zh/> 标记销毁元素
*
Expand Down
4 changes: 3 additions & 1 deletion packages/g6/src/utils/visibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const ORIGINAL_MAP = new WeakMap<DisplayObject, BaseStyleProps['visibility']>();
* <en/> Set the visibility of the shape instance
* @param shape - <zh/> 图形实例 | <en/> shape instance
* @param value - <zh/> 可见性 | <en/> visibility
* @param inherited - <zh/> 是否是来自继承样式 | <en/> Whether it is from inherited styles
* @param filter - <zh/> 筛选出需要设置可见性的图形 | <en/> Filter out the shapes that need to set visibility
* @remarks
* <zh/> 在设置 enableCSSParsing 为 false 的情况下,复合图形无法继承父属性,因此需要对所有子图形应用相同的可见性
Expand All @@ -17,6 +18,7 @@ const ORIGINAL_MAP = new WeakMap<DisplayObject, BaseStyleProps['visibility']>();
export function setVisibility(
shape: DisplayObject,
value: BaseStyleProps['visibility'],
inherited = false,
filter?: (shape: DisplayObject) => boolean,
) {
if (value === undefined) return;
Expand All @@ -26,7 +28,7 @@ export function setVisibility(

if (filter && !filter(current)) return walk();

if (current === shape) {
if (!inherited && current === shape) {
shape.style.visibility = value;
ORIGINAL_MAP.delete(shape);
walk(value);
Expand Down
Loading