跳至主要內容

transition

轉場是由於狀態變更導致元素進入或離開 DOM 時觸發。

當一個區塊(例如 {#if ...} 區塊)正在轉換退出時,它內部的所有元素,包括那些沒有自己轉場效果的元素,都會保留在 DOM 中,直到區塊中的每個轉場效果都完成。

transition: 指令表示雙向轉場效果,這表示轉場效果進行中可以平滑地反轉。

<script>
	import { fade } from 'svelte/transition';

	let visible = $state(false);
</script>

<button onclick={() => visible = !visible}>toggle</button>

{#if visible}
	<div transition:fade>fades in and out</div>
{/if}

內建轉場效果

可以從 svelte/transition 模組匯入一系列內建轉場效果。

局部 vs 全域

轉場效果預設為局部。局部轉場效果僅在它們所屬的區塊被建立或銷毀時播放,不會在父區塊被建立或銷毀時播放。

{#if x}
	{#if y}
		<p transition:fade>fades in and out only when y changes</p>

		<p transition:fade|global>fades in and out when x or y change</p>
	{/if}
{/if}

轉場參數

轉場效果可以有參數。

(雙重 {{花括號}} 不是特殊的語法;這是一個在表達式標籤內部的物件字面值。)

{#if visible}
	<div transition:fade={{ duration: 2000 }}>fades in and out over two seconds</div>
{/if}

自訂轉場函數

transition = (node: HTMLElementnode: HTMLElement, params: anyparams: any, 
options: {
    direction: "in" | "out" | "both";
}
options
: { direction: "in" | "out" | "both"direction: 'in' | 'out' | 'both' }) => {
delay?: number, duration?: number, easing?: (t: numbert: number) => number, css?: (t: numbert: number, u: numberu: number) => string, tick?: (t: numbert: number, u: numberu: number) => void }

轉場效果可以使用自訂函數。如果回傳的物件有 css 函數,Svelte 將為 網頁動畫產生關鍵影格。

傳遞給 csst 參數是在套用 easing 函數之後,介於 01 之間的值。進入轉場效果從 0 執行到 1退出轉場效果從 1 執行到 0 — 換句話說,1 是元素的自然狀態,就好像沒有套用任何轉場效果一樣。u 參數等於 1 - t

該函數在轉場效果開始之前,使用不同的 tu 參數重複呼叫。

應用程式
<script>
	import { elasticOut } from 'svelte/easing';

	/** @type {boolean} */
	export let visible;

	/**
	 * @param {HTMLElement} node
	 * @param {{ delay?: number, duration?: number, easing?: (t: number) => number }} params
	 */
	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})`
		};
	}
</script>

{#if visible}
	<div in:whoosh>whooshes in</div>
{/if}
<script lang="ts">
	import { elasticOut } from 'svelte/easing';

	export let visible: boolean;

	function whoosh(node: HTMLElement, params: { delay?: number, duration?: number, easing?: (t: number) => number }) {
		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})`
		};
	}
</script>

{#if visible}
	<div in:whoosh>whooshes in</div>
{/if}

自訂轉場函數也可以回傳一個 tick 函數,該函數會在轉場效果期間使用相同的 tu 參數呼叫。

如果可以使用 css 而不是 tick,請務必使用 — 網頁動畫可以在主執行緒之外執行,防止在較慢的裝置上出現卡頓。

應用程式
<script>
	export let visible = false;

	/**
	 * @param {HTMLElement} node
	 * @param {{ speed?: number }} params
	 */
	function typewriter(node, { speed = 1 }) {
		const valid = node.childNodes.length === 1 && node.childNodes[0].nodeType === Node.TEXT_NODE;

		if (!valid) {
			throw new Error(`This transition only works on elements with a single text node child`);
		}

		const text = node.textContent;
		const duration = text.length / (speed * 0.01);

		return {
			duration,
			tick: (t) => {
				const i = ~~(text.length * t);
				node.textContent = text.slice(0, i);
			}
		};
	}
</script>

{#if visible}
	<p in:typewriter={{ speed: 1 }}>The quick brown fox jumps over the lazy dog</p>
{/if}
<script lang="ts">
	export let visible = false;

	function typewriter(node: HTMLElement, { speed = 1 }: { speed?: number }) {
		const valid = node.childNodes.length === 1 && node.childNodes[0].nodeType === Node.TEXT_NODE;

		if (!valid) {
			throw new Error(`This transition only works on elements with a single text node child`);
		}

		const text = node.textContent;
		const duration = text.length / (speed * 0.01);

		return {
			duration,
			tick: (t) => {
				const i = ~~(text.length * t);
				node.textContent = text.slice(0, i);
			}
		};
	}
</script>

{#if visible}
	<p in:typewriter={{ speed: 1 }}>The quick brown fox jumps over the lazy dog</p>
{/if}

如果轉場效果回傳函數而不是轉場物件,則該函數將在下一個微任務中呼叫。這允許協調多個轉場效果,使 交叉淡入淡出效果成為可能。

轉場函數也會接收第三個參數 options,其中包含有關轉場效果的資訊。

options 物件中的可用值為

  • direction - 根據轉場效果的類型,為 inoutboth 其中之一

轉場事件

具有轉場效果的元素除了任何標準 DOM 事件之外,還會派發以下事件

  • introstart
  • introend
  • outrostart
  • outroend
{#if visible}
	<p
		transition:fly={{ y: 200, duration: 2000 }}
		onintrostart={() => (status = 'intro started')}
		onoutrostart={() => (status = 'outro started')}
		onintroend={() => (status = 'intro ended')}
		onoutroend={() => (status = 'outro ended')}
	>
		Flies in and out
	</p>
{/if}

在 GitHub 上編輯此頁面

上一頁 下一頁