diff --git a/packages/g6/__tests__/bugs/utils-set-visibility.spec.ts b/packages/g6/__tests__/bugs/utils-set-visibility.spec.ts
new file mode 100644
index 00000000000..1d08abe9dd6
--- /dev/null
+++ b/packages/g6/__tests__/bugs/utils-set-visibility.spec.ts
@@ -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');
+ });
+});
diff --git a/packages/g6/__tests__/snapshots/bugs/utils-set-visibility/default.svg b/packages/g6/__tests__/snapshots/bugs/utils-set-visibility/default.svg
new file mode 100644
index 00000000000..ee65fef81cc
--- /dev/null
+++ b/packages/g6/__tests__/snapshots/bugs/utils-set-visibility/default.svg
@@ -0,0 +1,40 @@
+
\ No newline at end of file
diff --git a/packages/g6/__tests__/snapshots/bugs/utils-set-visibility/hidden.svg b/packages/g6/__tests__/snapshots/bugs/utils-set-visibility/hidden.svg
new file mode 100644
index 00000000000..9adc07d8001
--- /dev/null
+++ b/packages/g6/__tests__/snapshots/bugs/utils-set-visibility/hidden.svg
@@ -0,0 +1,40 @@
+
\ No newline at end of file
diff --git a/packages/g6/__tests__/snapshots/bugs/utils-set-visibility/visible.svg b/packages/g6/__tests__/snapshots/bugs/utils-set-visibility/visible.svg
new file mode 100644
index 00000000000..01d1e7059a4
--- /dev/null
+++ b/packages/g6/__tests__/snapshots/bugs/utils-set-visibility/visible.svg
@@ -0,0 +1,40 @@
+
\ No newline at end of file
diff --git a/packages/g6/__tests__/unit/utils/visibility.spec.ts b/packages/g6/__tests__/unit/utils/visibility.spec.ts
index 26d196beb5d..67e6037f4f5 100644
--- a/packages/g6/__tests__/unit/utils/visibility.spec.ts
+++ b/packages/g6/__tests__/unit/utils/visibility.spec.ts
@@ -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');
@@ -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');
diff --git a/packages/g6/src/behaviors/optimize-viewport-transform.ts b/packages/g6/src/behaviors/optimize-viewport-transform.ts
index 7b29be3468a..61be23027c8 100644
--- a/packages/g6/src/behaviors/optimize-viewport-transform.ts
+++ b/packages/g6/src/behaviors/optimize-viewport-transform.ts
@@ -72,6 +72,7 @@ export class OptimizeViewportTransform extends BaseBehavior !!shape.className && !excludedClassnames?.includes(shape.className),
);
});
diff --git a/packages/g6/src/elements/shapes/base-shape.ts b/packages/g6/src/elements/shapes/base-shape.ts
index 5994a71b4f2..c5609985d13 100644
--- a/packages/g6/src/elements/shapes/base-shape.ts
+++ b/packages/g6/src/elements/shapes/base-shape.ts
@@ -222,7 +222,7 @@ export abstract class BaseShape extends
private setVisibility() {
const { visibility } = this.attributes;
- setVisibility(this, visibility);
+ setVisibility(this, visibility, true);
}
public destroy(): void {
diff --git a/packages/g6/src/runtime/element.ts b/packages/g6/src/runtime/element.ts
index cf6691797ac..0d4c121a848 100644
--- a/packages/g6/src/runtime/element.ts
+++ b/packages/g6/src/runtime/element.ts
@@ -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';
@@ -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 {
@@ -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,
@@ -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?.();
},
@@ -498,6 +503,8 @@ export class ElementController {
});
}
+ private visibilityCache = new WeakMap();
+
/**
* 标记销毁元素
*
diff --git a/packages/g6/src/utils/visibility.ts b/packages/g6/src/utils/visibility.ts
index a09575c555c..7b24ecb870d 100644
--- a/packages/g6/src/utils/visibility.ts
+++ b/packages/g6/src/utils/visibility.ts
@@ -8,6 +8,7 @@ const ORIGINAL_MAP = new WeakMap();
* Set the visibility of the shape instance
* @param shape - 图形实例 | shape instance
* @param value - 可见性 | visibility
+ * @param inherited - 是否是来自继承样式 | Whether it is from inherited styles
* @param filter - 筛选出需要设置可见性的图形 | Filter out the shapes that need to set visibility
* @remarks
* 在设置 enableCSSParsing 为 false 的情况下,复合图形无法继承父属性,因此需要对所有子图形应用相同的可见性
@@ -17,6 +18,7 @@ const ORIGINAL_MAP = new WeakMap();
export function setVisibility(
shape: DisplayObject,
value: BaseStyleProps['visibility'],
+ inherited = false,
filter?: (shape: DisplayObject) => boolean,
) {
if (value === undefined) return;
@@ -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);