首页 / Svelte 5 入门教程 / 过渡 transition:

Svelte 5 入门教程

过渡 transition:

本教程共 50 篇 · 第 23 篇 · 更新于 2026-08-05 · 约 7 分钟阅读

SvelteSvelte 5transition过渡动画fadefly

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透明度变化durationdelay
fly从指定位置飞入xydurationopacity
slide高度展开/收起durationaxis
scale缩放startdurationopacity
blur模糊+透明度amountdurationopacity
drawSVG 描边durationspeeddelay

过渡参数

所有过渡都支持三个基础参数: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

elasticOutbounceOut 适合做弹出效果,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}

配置对象的关键字段:

字段类型说明
delaynumber延迟开始时间(毫秒)
durationnumber过渡时长(毫秒)
easing(t) => number缓动函数
css(t, u) => string返回 CSS 样式字符串
tick(t, u) => void每帧调用的回调

关于 tu 参数:

  • t 是经过缓动函数处理后的进度值,从 0 到 1(进入)或从 1 到 0(离开)
  • u 等于 1 - t
  • 1 代表元素的自然状态

css vs tick

自定义过渡可以用 csstick 两种方式。优先用 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 提供 fadeflyslidescaleblurdraw 等内置过渡
  • 三个基础参数:delaydurationeasing
  • svelte/easing 提供 30 多种缓动函数,elasticOutcubicOut 最常用
  • 自定义过渡返回配置对象,csstick 性能更好
  • 过渡元素会触发 introstart/introend/outrostart/outroend 四个事件