Skip to content

Commit 4a5d262

Browse files
author
ian.lxl
committed
fix: basic shapes update
1 parent a2505be commit 4a5d262

6 files changed

Lines changed: 212 additions & 4 deletions

packages/f-engine/src/canvas/render/index.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,17 +185,20 @@ function createElement(parent: VNode, element: JSX.Element): VNode | VNode[] | n
185185
});
186186
}
187187

188-
function destroyElement(vNode: VNode | VNode[] | null) {
188+
function destroyElement(vNode: VNode | VNode[] | null, nextVNode?: VNode) {
189189
Children.map(vNode, (node: VNode | null) => {
190190
if (!node) return;
191-
const { component, children } = node;
191+
const { component, children, shape, tag } = node;
192192
if (component) {
193193
component.willUnmount();
194194
destroyElement(children);
195195
component.didUnmount();
196196
component.destroy();
197-
} else {
197+
} else if (children) {
198198
destroyElement(children);
199+
} else if (tag === Shape && shape) {
200+
// 更新模式时销毁上个节点
201+
nextVNode && shape.destroy();
199202
}
200203
});
201204
}
@@ -214,7 +217,7 @@ function updateElement(parent: VNode, nextElement: JSX.Element, lastElement: VNo
214217
}
215218

216219
const nextVNode = createVNode(parent, nextElement as VNode);
217-
destroyElement(lastElement);
220+
destroyElement(lastElement, nextVNode);
218221
return nextVNode;
219222
}
220223

3.39 KB
Loading
Loading
Loading
Loading

packages/f-engine/test/canvas/render/vnodeUpdate.test.tsx

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,209 @@ describe('vnode 更新', () => {
4242

4343
expect(ref.current._vNode.props.update).toBe(true);
4444
});
45+
46+
it('基础图形更新', async () => {
47+
const context = createContext();
48+
const { props } = (
49+
<Canvas context={context}>
50+
<rect
51+
style={{
52+
width: 36,
53+
height: 36,
54+
fill: 'red',
55+
}}
56+
/>
57+
</Canvas>
58+
);
59+
60+
const canvas = new Canvas(props);
61+
await canvas.render();
62+
63+
const { props: nextProps } = (
64+
<Canvas context={context}>
65+
<circle
66+
style={{
67+
cx: 80,
68+
cy: 30,
69+
r: 20,
70+
lineWidth: 2,
71+
stroke: '#e45649',
72+
fill: 'blue',
73+
}}
74+
/>
75+
</Canvas>
76+
);
77+
await delay(500);
78+
await canvas.update(nextProps);
79+
80+
await delay(200);
81+
expect(context).toMatchImageSnapshot();
82+
});
83+
84+
it('基础图形销毁带离场动画', async () => {
85+
const context = createContext();
86+
const { props } = (
87+
<Canvas context={context}>
88+
<rect
89+
style={{
90+
width: 36,
91+
height: 36,
92+
fill: 'red',
93+
}}
94+
animation={{
95+
leave: {
96+
easing: 'ease-out',
97+
duration: 500,
98+
property: ['width', 'height'],
99+
start: {
100+
width: 36,
101+
height: 36,
102+
},
103+
end: {
104+
width: 0,
105+
height: 0,
106+
},
107+
},
108+
}}
109+
/>
110+
</Canvas>
111+
);
112+
113+
const canvas = new Canvas(props);
114+
await canvas.render();
115+
116+
await delay(200);
117+
const { props: nextProps } = (
118+
<Canvas context={context}>
119+
</Canvas>
120+
);
121+
await canvas.update(nextProps);
122+
await delay(600);
123+
expect(context).toMatchImageSnapshot();
124+
});
125+
126+
it('基础图形更新带离场动画', async () => {
127+
const context = createContext();
128+
const { props } = (
129+
<Canvas context={context}>
130+
<rect
131+
style={{
132+
width: 36,
133+
height: 36,
134+
fill: 'red',
135+
}}
136+
animation={{
137+
leave: {
138+
easing: 'ease-out',
139+
duration: 500,
140+
property: ['width', 'height'],
141+
start: {
142+
width: 36,
143+
height: 36,
144+
},
145+
end: {
146+
width: 0,
147+
height: 0,
148+
},
149+
},
150+
}}
151+
/>
152+
</Canvas>
153+
);
154+
155+
const canvas = new Canvas(props);
156+
await canvas.render();
157+
158+
await delay(200);
159+
const { props: nextProps } = (
160+
<Canvas context={context}>
161+
<circle
162+
style={{
163+
cx: 80,
164+
cy: 30,
165+
r: 20,
166+
lineWidth: 2,
167+
stroke: '#e45649',
168+
fill: 'blue',
169+
}}
170+
/>
171+
</Canvas>
172+
);
173+
174+
// 无离场动画效果
175+
await canvas.update(nextProps);
176+
await delay(600);
177+
expect(context).toMatchImageSnapshot();
178+
});
179+
180+
it('基础图形更新带入场动画', async () => {
181+
const context = createContext();
182+
const { props } = (
183+
<Canvas context={context}>
184+
<circle
185+
style={{
186+
cx: 30,
187+
cy: 30,
188+
r: 20,
189+
lineWidth: 2,
190+
stroke: '#e45649',
191+
fill: 'blue',
192+
}}
193+
animation={{
194+
appear: {
195+
easing: 'ease-in',
196+
duration: 300,
197+
property: ['r'],
198+
start: {
199+
r: 0,
200+
},
201+
end: {
202+
r: 20,
203+
},
204+
},
205+
}}
206+
/>
207+
</Canvas>
208+
);
209+
210+
await delay(200);
211+
const canvas = new Canvas(props);
212+
await canvas.render();
213+
214+
await delay(500);
215+
const { props: nextProps } = (
216+
<Canvas context={context}>
217+
<rect
218+
style={{
219+
x: 80,
220+
y: 30,
221+
width: 36,
222+
height: 36,
223+
fill: 'red',
224+
}}
225+
animation={{
226+
update: {
227+
easing: 'ease-out',
228+
duration: 500,
229+
property: ['width', 'height'],
230+
start: {
231+
width: 0,
232+
height: 0,
233+
},
234+
end: {
235+
width: 36,
236+
height: 36,
237+
},
238+
},
239+
}}
240+
/>
241+
</Canvas>
242+
);
243+
244+
// 执行入场动画
245+
await canvas.update(nextProps);
246+
await delay(600);
247+
expect(context).toMatchImageSnapshot();
248+
});
249+
45250
});

0 commit comments

Comments
 (0)