过渡 transition:
本教程共 50 篇 · 第 23 篇 · 更新于 2026-08-05 · 约 7 分钟阅读
23. 过渡 transition:
本节目标:学会用 transition: 指令给元素添加进出动画,掌握内置过渡效果和参数配置,理解缓动函数,能够编写自定义过渡函数。
什么是过渡
过渡(Transition)是指元素进入或离开 DOM 时的动画效果。比如一个弹窗淡入淡出、一个菜单从侧边滑出。
打个比方,过渡就像演员上台下场时的出场效果。直接走上台太生硬,加个聚光灯渐亮的效果就好多了。
在 Svelte 里,当你用 {#if} 控制元素显示隐藏时,transition: 指令可以让这个过程带上动画。
<script>
import { fade } from 'svelte/transition';
let visible = $state(false);
</script>
<button onclick={() => visible = !visible}>切换</button>
{#if visible}
<div transition:fade>淡入淡出</div>
{/if}
transition: 是双向的——元素出现时用进入动画,消失时用离开动画,而且过程可以中途逆转。
内置过渡效果
Svelte 从 svelte/transition 模块提供了一组内置过渡函数。
fade 淡入淡出
最简单的过渡,通过调整透明度实现。
<script>
import { fade } from 'svelte/transition';
let visible = $state(false);
</script>
{#if visible}
<div transition:fade>淡入淡出</div>
{/if}
fly 飞入飞出
元素从指定方向飞入,离开时飞回。
<script>
import { fly } from 'svelte/transition';
let visible = $state(false);
</script>
{#if visible}
<div transition:fly={{ y: 200, duration: 1000 }}>
从下方飞入
</div>
{/if}
slide 滑入滑出
元素高度从 0 展开,或收回到 0。
<script>
import { slide } from 'svelte/transition';
let visible = $state(false);
</script>
{#if visible}
<div transition:slide>滑动展开</div>
{/if}
scale 缩放
元素从缩小状态放大出现,或缩小消失。
<script>
import { scale } from 'svelte/transition';
let visible = $state(false);
</script>
{#if visible}
<div transition:scale={{ start: 0.5, duration: 800 }}>
缩放过渡
</div>
{/if}
blur 模糊
元素带模糊滤镜和透明度变化。
<script>
import { blur } from 'svelte/transition';
let visible = $state(false);
</script>
{#if visible}
<div transition:blur={{ amount: 5 }}>模糊过渡</div>
{/if}
draw 描边
专门用于 SVG 元素,像画笔一样描绘路径。
<script>
import { draw } from 'svelte/transition';
let visible = $state(false);
</script>
{#if visible}
<svg viewBox="0 0 100 100">
<path
transition:draw={{ duration: 2000 }}
d="M10,50 Q25,10 50,50 T90,50"
fill="none"
stroke="black"
stroke-width="3"
/>
</svg>
{/if}
内置过渡一览表
| 过渡 | 效果 | 常用参数 |
|---|---|---|
fade | 透明度变化 | duration、delay |
fly | 从指定位置飞入 | x、y、duration、opacity |
slide | 高度展开/收起 | duration、axis |
scale | 缩放 | start、duration、opacity |
blur | 模糊+透明度 | amount、duration、opacity |
draw | SVG 描边 | duration、speed、delay |
过渡参数
所有过渡都支持三个基础参数:delay(延迟)、duration(时长)、easing(缓动函数)。
<script>
import { fade } from 'svelte/transition';
let visible = $state(false);
</script>
{#if visible}
<div transition:fade={{ duration: 2000, delay: 500 }}>
延迟 0.5 秒后,用 2 秒淡入淡出
</div>
{/if}
Note
duration的单位是毫秒。{{ }}双花括号不是特殊语法,外层{}是 Svelte 表达式标记,内层{}是对象字面量。
缓动函数
缓动函数控制动画的节奏。匀速变化看起来很机械,加上缓动就自然多了。
Svelte 从 svelte/easing 模块提供了 30 多种缓动函数。常用的有:
<script>
import { fly } from 'svelte/transition';
import { elasticOut } from 'svelte/easing';
let visible = $state(false);
</script>
{#if visible}
<div transition:fly={{ y: 100, duration: 1000, easing: elasticOut }}>
弹性飞入
</div>
{/if}
常用缓动函数一览:
| 缓动 | 效果 |
|---|---|
linear | 匀速 |
cubicOut | 先快后慢 |
cubicIn | 先慢后快 |
cubicInOut | 两头慢中间快 |
elasticOut | 弹性弹出 |
bounceOut | 弹跳 |
backOut | 超出后回弹 |
Tip
elasticOut和bounceOut适合做弹出效果,cubicOut适合做通用过渡。你可以去 Svelte 官网的 easing 可视化页面感受每种函数的效果。
本地与全局过渡
默认情况下,过渡是”本地”的——只在元素所属的块创建或销毁时播放。
{#if x}
{#if y}
<!-- 只在 y 变化时播放过渡 -->
<p transition:fade>本地过渡</p>
<!-- x 或 y 变化时都播放 -->
<p transition:fade|global>全局过渡</p>
{/if}
{/if}
自定义过渡函数
内置过渡不够用?你可以自己写。
过渡函数接收两个参数:node(DOM 元素)和 params(参数对象)。返回一个配置对象。
<script>
import { elasticOut } from 'svelte/easing';
function whoosh(node, params) {
const existingTransform = getComputedStyle(node).transform.replace('none', '');
return {
delay: params.delay || 0,
duration: params.duration || 400,
easing: params.easing || elasticOut,
css: (t, u) => `transform: ${existingTransform} scale(${t})`
};
}
let visible = $state(false);
</script>
{#if visible}
<div in:whoosh={{ duration: 600 }}>自定义弹入</div>
{/if}
配置对象的关键字段:
| 字段 | 类型 | 说明 |
|---|---|---|
delay | number | 延迟开始时间(毫秒) |
duration | number | 过渡时长(毫秒) |
easing | (t) => number | 缓动函数 |
css | (t, u) => string | 返回 CSS 样式字符串 |
tick | (t, u) => void | 每帧调用的回调 |
关于 t 和 u 参数:
t是经过缓动函数处理后的进度值,从 0 到 1(进入)或从 1 到 0(离开)u等于1 - t1代表元素的自然状态
css vs tick
自定义过渡可以用 css 或 tick 两种方式。优先用 css,因为它利用 Web Animations API,可以在主线程之外运行,避免卡顿。
<script>
// 用 css:推荐,性能更好
function fadeScale(node) {
return {
duration: 400,
css: (t) => `opacity: ${t}; transform: scale(${t})`
};
}
// 用 tick:适合需要逐帧操作 DOM 的场景
function typewriter(node, { speed = 1 }) {
const text = node.textContent;
const duration = text.length / (speed * 0.01);
return {
duration,
tick: (t) => {
const i = Math.floor(text.length * t);
node.textContent = text.slice(0, i);
}
};
}
</script>
Note如果能用
css解决就不要用tick。Web 动画可以在主线程之外运行,对性能更友好。tick适合打字机效果这种需要逐帧修改 DOM 内容的场景。
过渡事件
有过渡的元素会触发四个额外事件:
introstart:进入过渡开始introend:进入过渡结束outrostart:离开过渡开始outroend:离开过渡结束
<script>
import { fly } from 'svelte/transition';
let visible = $state(false);
let status = $state('');
</script>
{#if visible}
<p
transition:fly={{ y: 200, duration: 2000 }}
onintrostart={() => status = '进入开始'}
onintroend={() => status = '进入结束'}
onoutrostart={() => status = '离开开始'}
onoutroend={() => status = '离开结束'}
>
{status}
</p>
{/if}
<button onclick={() => visible = !visible}>切换</button>
本节回顾
transition:是双向过渡指令,元素进入和离开时都播放动画- Svelte 提供
fade、fly、slide、scale、blur、draw等内置过渡 - 三个基础参数:
delay、duration、easing svelte/easing提供 30 多种缓动函数,elasticOut和cubicOut最常用- 自定义过渡返回配置对象,
css比tick性能更好 - 过渡元素会触发
introstart/introend/outrostart/outroend四个事件