如何用Spring实现Svelte的Slide过渡效果(替代时长+缓动)
实现带Spring特性的Svelte Slide过渡
核心思路
Slide过渡的关键是动态计算容器尺寸并结合Spring动画驱动尺寸变化——不同于仅靠transform实现的位移动画,Slide需要容器收缩/扩展来“挤出/拉入”元素,这也是它比transform动画复杂的原因。
实现步骤
1. 基础竖向Slide(固定内容高度)
先通过Spring驱动容器高度变化,搭配overflow: hidden实现基础的展开/收起效果:
<script> import { spring } from 'svelte/motion'; let isOpen = false; // 自定义Spring弹性参数,stiffness控制弹性强度,damping控制减速速度 const springConfig = { stiffness: 0.15, damping: 0.2 }; // 用Spring管理容器高度,初始为0(关闭状态) const containerHeight = spring(0, springConfig); </script> <button on:click={() => { isOpen = !isOpen; // 根据状态设置目标高度 containerHeight.set(isOpen ? '100%' : 0); }}> {isOpen ? '收起' : '展开'} </button> <div style="overflow: hidden; height: {$containerHeight}; border: 1px solid #eee;"> <div> <p>这是带Spring弹性的Slide过渡内容</p> <p>更多示例内容...</p> </div> </div>
2. 适配动态内容的竖向Slide
如果内容高度不固定,需要先获取内容的实际尺寸再传给Spring:
<script> import { spring } from 'svelte/motion'; import { tick } from 'svelte'; let isOpen = false; let contentElement; const springConfig = { stiffness: 0.15, damping: 0.2 }; const containerHeight = spring(0, springConfig); async function toggle() { isOpen = !isOpen; await tick(); // 等待DOM更新,确保拿到最新的内容尺寸 const contentHeight = contentElement.offsetHeight; containerHeight.set(isOpen ? contentHeight : 0); } </script> <button on:click={toggle}> {isOpen ? '收起' : '展开'} </button> <div style="overflow: hidden; height: {$containerHeight}px; border: 1px solid #eee;"> <div bind:this={contentElement}> <!-- 动态内容示例:随机生成的列表 --> <ul> {#each Array(Math.floor(Math.random()*5)+3) as _, i} <li>动态列表项 {i+1}</li> {/each} </ul> </div> </div>
3. 横向Slide(侧边栏场景)
把高度逻辑换成宽度,调整overflow方向即可实现横向Slide:
<script> import { spring } from 'svelte/motion'; import { tick } from 'svelte'; let isOpen = false; let contentElement; const springConfig = { stiffness: 0.2, damping: 0.18 }; const containerWidth = spring(0, springConfig); async function toggle() { isOpen = !isOpen; await tick(); const contentWidth = contentElement.offsetWidth; containerWidth.set(isOpen ? contentWidth : 0); } </script> <button on:click={toggle}> {isOpen ? '收起侧边栏' : '展开侧边栏'} </button> <div style="overflow: hidden; width: {$containerWidth}px; display: inline-block; border: 1px solid #eee;"> <div bind:this={contentElement} style="white-space: nowrap; padding: 10px;"> <span>横向Slide侧边栏</span> <span> | 菜单1 | 菜单2 | 菜单3</span> </div> </div>
关键注意事项
- 避免布局抖动:始终给容器加
overflow: hidden,防止动画过程中出现滚动条或内容溢出。 - Spring参数调试:
stiffness越大弹性越强,damping越大减速越快——侧边栏适合用稍大的stiffness,下拉面板适合用较小的stiffness。 - DOM更新时机:必须用
await tick()等待DOM渲染完成后再获取内容尺寸,否则会拿到旧值导致动画异常。
内容的提问来源于stack exchange,提问作者Asaf Agranat
相关产品推荐
相关产品推荐

