mirror of
https://gitee.com/antv/g6.git
synced 2024-11-29 18:28:19 +08:00
fix: fix part of element lost when set visibility in animation
This commit is contained in:
parent
ab97b6a84c
commit
596d024aed
35
packages/g6/__tests__/bugs/utils-set-visibility.spec.ts
Normal file
35
packages/g6/__tests__/bugs/utils-set-visibility.spec.ts
Normal file
@ -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');
|
||||
});
|
||||
});
|
@ -0,0 +1,40 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" style="background: transparent; position: absolute; outline: none;" color-interpolation-filters="sRGB" tabindex="1">
|
||||
<defs/>
|
||||
<g >
|
||||
<g fill="none">
|
||||
<g fill="none" class="elements">
|
||||
<g fill="none" x="100" y="100" transform="matrix(1,0,0,1,100,100)">
|
||||
<g>
|
||||
<circle fill="rgba(23,131,255,1)" class="key" stroke-width="0" stroke="rgba(0,0,0,1)" r="16"/>
|
||||
</g>
|
||||
<g fill="none" class="label" transform="matrix(1,0,0,1,0,18)">
|
||||
<g>
|
||||
<text fill="rgba(0,0,0,1)" dominant-baseline="central" paint-order="stroke" dx="0.5" dy="11.5px" class="text" font-size="12" font-family="system-ui, sans-serif" text-anchor="middle" fill-opacity="0.85" font-weight="400">
|
||||
label
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
<g fill="none" class="icon" width="25.6" height="25.6">
|
||||
<g>
|
||||
<text fill="rgba(255,255,255,1)" dominant-baseline="central" paint-order="stroke" dx="0.5" class="icon" text-anchor="middle" width="25.6" height="25.6" font-size="16">
|
||||
icon
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
<g fill="none" class="badge-0" transform="matrix(1,0,0,1,16,-16)">
|
||||
<g fill="none" class="label">
|
||||
<g>
|
||||
<path fill="rgba(126,146,181,1)" d="M 4.5,0 l 0.879999999999999,0 a 8.5,8.5,0,0,1,8.5,8.5 l 0,0 a 8.5,8.5,0,0,1,-8.5,8.5 l -0.879999999999999,0 a 8.5,8.5,0,0,1,-8.5,-8.5 l 0,0 a 8.5,8.5,0,0,1,8.5,-8.5 z" class="background" stroke-width="0" x="-4" y="0" width="17.88" height="17"/>
|
||||
</g>
|
||||
<g>
|
||||
<text fill="rgba(255,255,255,1)" dominant-baseline="central" paint-order="stroke" dx="0.5" dy="8.5px" class="text" font-size="8" font-family="system-ui, sans-serif" text-anchor="left">
|
||||
b1
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.0 KiB |
@ -0,0 +1,40 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" style="background: transparent; position: absolute; outline: none;" color-interpolation-filters="sRGB" tabindex="1">
|
||||
<defs/>
|
||||
<g >
|
||||
<g fill="none">
|
||||
<g fill="none" class="elements">
|
||||
<g fill="none" x="100" y="100" transform="matrix(1,0,0,1,100,100)">
|
||||
<g>
|
||||
<circle fill="rgba(23,131,255,1)" class="key" stroke-width="0" stroke="rgba(0,0,0,1)" r="16" opacity="0" visibility="hidden"/>
|
||||
</g>
|
||||
<g fill="none" class="label" transform="matrix(1,0,0,1,0,18)">
|
||||
<g>
|
||||
<text fill="rgba(0,0,0,1)" dominant-baseline="central" paint-order="stroke" dx="0.5" dy="11.5px" class="text" font-size="12" font-family="system-ui, sans-serif" text-anchor="middle" fill-opacity="0.85" font-weight="400" opacity="0" visibility="hidden">
|
||||
label
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
<g fill="none" class="icon" width="25.6" height="25.6">
|
||||
<g>
|
||||
<text fill="rgba(255,255,255,1)" dominant-baseline="central" paint-order="stroke" dx="0.5" class="icon" text-anchor="middle" width="25.6" height="25.6" font-size="16" opacity="0" visibility="hidden">
|
||||
icon
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
<g fill="none" class="badge-0" transform="matrix(1,0,0,1,16,-16)">
|
||||
<g fill="none" class="label">
|
||||
<g>
|
||||
<path fill="rgba(126,146,181,1)" d="M 4.5,0 l 0.879999999999999,0 a 8.5,8.5,0,0,1,8.5,8.5 l 0,0 a 8.5,8.5,0,0,1,-8.5,8.5 l -0.879999999999999,0 a 8.5,8.5,0,0,1,-8.5,-8.5 l 0,0 a 8.5,8.5,0,0,1,8.5,-8.5 z" class="background" stroke-width="0" x="-4" y="0" width="17.88" height="17" opacity="0" visibility="hidden"/>
|
||||
</g>
|
||||
<g>
|
||||
<text fill="rgba(255,255,255,1)" dominant-baseline="central" paint-order="stroke" dx="0.5" dy="8.5px" class="text" font-size="8" font-family="system-ui, sans-serif" text-anchor="left" opacity="0" visibility="hidden">
|
||||
b1
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
@ -0,0 +1,40 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" style="background: transparent; position: absolute; outline: none;" color-interpolation-filters="sRGB" tabindex="1">
|
||||
<defs/>
|
||||
<g >
|
||||
<g fill="none">
|
||||
<g fill="none" class="elements">
|
||||
<g fill="none" x="100" y="100" transform="matrix(1,0,0,1,100,100)">
|
||||
<g>
|
||||
<circle fill="rgba(23,131,255,1)" class="key" stroke-width="0" stroke="rgba(0,0,0,1)" r="16" visibility="visible"/>
|
||||
</g>
|
||||
<g fill="none" class="label" transform="matrix(1,0,0,1,0,18)">
|
||||
<g>
|
||||
<text fill="rgba(0,0,0,1)" dominant-baseline="central" paint-order="stroke" dx="0.5" dy="11.5px" class="text" font-size="12" font-family="system-ui, sans-serif" text-anchor="middle" fill-opacity="0.85" font-weight="400" visibility="visible">
|
||||
label
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
<g fill="none" class="icon" width="25.6" height="25.6">
|
||||
<g>
|
||||
<text fill="rgba(255,255,255,1)" dominant-baseline="central" paint-order="stroke" dx="0.5" class="icon" text-anchor="middle" width="25.6" height="25.6" font-size="16" visibility="visible">
|
||||
icon
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
<g fill="none" class="badge-0" transform="matrix(1,0,0,1,16,-16)">
|
||||
<g fill="none" class="label">
|
||||
<g>
|
||||
<path fill="rgba(126,146,181,1)" d="M 4.5,0 l 0.879999999999999,0 a 8.5,8.5,0,0,1,8.5,8.5 l 0,0 a 8.5,8.5,0,0,1,-8.5,8.5 l -0.879999999999999,0 a 8.5,8.5,0,0,1,-8.5,-8.5 l 0,0 a 8.5,8.5,0,0,1,8.5,-8.5 z" class="background" stroke-width="0" x="-4" y="0" width="17.88" height="17" visibility="visible"/>
|
||||
</g>
|
||||
<g>
|
||||
<text fill="rgba(255,255,255,1)" dominant-baseline="central" paint-order="stroke" dx="0.5" dy="8.5px" class="text" font-size="8" font-family="system-ui, sans-serif" text-anchor="left" visibility="visible">
|
||||
b1
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
@ -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');
|
||||
|
@ -72,6 +72,7 @@ export class OptimizeViewportTransform extends BaseBehavior<OptimizeViewportTran
|
||||
setVisibility(
|
||||
element,
|
||||
visibility,
|
||||
false,
|
||||
(shape) => !!shape.className && !excludedClassnames?.includes(shape.className),
|
||||
);
|
||||
});
|
||||
|
@ -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 {
|
||||
|
@ -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<Element, BaseStyleProps['visibility']>();
|
||||
|
||||
/**
|
||||
* <zh/> 标记销毁元素
|
||||
*
|
||||
|
@ -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 的情况下,复合图形无法继承父属性,因此需要对所有子图形应用相同的可见性
|
||||
@ -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;
|
||||
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user