如何结合animate:flip与in/out:fade实现列表动画?堆叠问题求助
问题分析与解决方案
你遇到的问题并非animate:flip和transition:fade(in/out)不能同时使用,而是默认的淡出过渡会修改元素尺寸导致布局提前塌陷,进而让flip动画的位置计算异常,最终出现旧元素堆叠的现象。
默认情况下,Svelte的out:fade过渡会在执行时给元素添加height: 0; width: 0; overflow: hidden样式,这会让元素立刻脱离正常布局,剩余元素提前移动到目标位置,而正在淡出的旧元素则因布局塌陷被挤到列表顶部/底部堆叠。
解决方案:自定义淡出过渡,保持元素布局空间
修改out:fade的配置,覆盖默认的CSS样式,让淡出过程中仅改变元素透明度,不修改尺寸,确保布局在淡出完成前保持稳定,这样flip动画就能基于正确的初始位置计算移动路径。
修改后的完整代码:
<script> import { flip } from 'svelte/animate' import { fade } from 'svelte/transition' let startInt = 0 $: items = Array(5).fill().map((x,i) => i+startInt) function shiftDown() { startInt = startInt + 3 } function shiftUp() { startInt = startInt - 3 } </script> <a href="#" on:click|preventDefault="{e => shiftUp()}">up</a> {#each items as item (item)} <div animate:flip="{{delay: 1000, duration: 1000}}" in:fade="{{delay: 2000, duration: 1000}}" out:fade="{{ duration: 1000, css: (t) => `opacity: ${t};` }}" > {item} </div> {/each} <a href="#" on:click|preventDefault="{e => shiftDown()}">down</a>
动画时序说明
这样修改后,动画会严格按照你期望的序列执行:
- 0-1000ms:旧元素仅执行透明度淡出,保持原有布局空间,不会影响其他元素位置
- 1000-2000ms:旧元素淡出完成后被移除,
flip动画触发,剩余元素从旧位置平滑移动到新位置 - 2000-3000ms:
flip动画完成后,新元素开始淡入
内容的提问来源于stack exchange,提问作者pejalo
相关产品推荐
相关产品推荐

