You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 10:55:07