跳至主要內容

animate

帶有 key 的 each 區塊的內容重新排序時,會觸發動畫。當元素新增或移除時,動畫不會執行,只有在 each 區塊中現有資料項目的索引變更時才會執行。animate 指令必須位於帶有 key 的 each 區塊的直接子元素上。

動畫可以搭配 Svelte 的內建動畫函式自訂動畫函式使用。

<!-- When `list` is reordered the animation will run -->
{#each list as item, index (item)}
	<li animate:flip>{item}</li>
{/each}

動畫參數

與 actions 和 transitions 一樣,動畫可以有參數。

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

{#each list as item, index (item)}
	<li animate:flip={{ delay: 500 }}>{item}</li>
{/each}

自訂動畫函式

animation = (node: HTMLElementnode: HTMLElement, { from: anyfrom: type DOMRect: anyDOMRect, to: anyto: type DOMRect: anyDOMRect } , params: anyparams: any) => {
	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
}

動畫可以使用自訂函式,這些函式會提供 node、一個 animation 物件以及任何 parameters 作為參數。animation 參數是一個物件,包含 fromto 屬性,每個屬性都包含一個 DOMRect,描述元素在 startend 位置的幾何形狀。from 屬性是元素在其起始位置的 DOMRect,而 to 屬性是元素在清單重新排序且 DOM 更新後在其最終位置的 DOMRect。

如果回傳的物件具有 css 方法,Svelte 將建立一個在元素上播放的 web 動畫

傳遞給 csst 參數是一個值,在套用 easing 函式後,該值會從 0 變為 1u 參數等於 1 - t

該函式在動畫開始之前會重複呼叫,使用不同的 tu 參數。

App
<script>
	import { cubicOut } from 'svelte/easing';

	/**
	 * @param {HTMLElement} node
	 * @param {{ from: DOMRect; to: DOMRect }} states
	 * @param {any} params
	 */
	function whizz(node, { from, to }, params) {
		const dx = from.left - to.left;
		const dy = from.top - to.top;

		const d = Math.sqrt(dx * dx + dy * dy);

		return {
			delay: 0,
			duration: Math.sqrt(d) * 120,
			easing: cubicOut,
			css: (t, u) => `transform: translate(${u * dx}px, ${u * dy}px) rotate(${t * 360}deg);`
		};
	}
</script>

{#each list as item, index (item)}
	<div animate:whizz>{item}</div>
{/each}
<script lang="ts">
	import { cubicOut } from 'svelte/easing';

	function whizz(node: HTMLElement, { from, to }: { from: DOMRect; to: DOMRect }, params: any) {
		const dx = from.left - to.left;
		const dy = from.top - to.top;

		const d = Math.sqrt(dx * dx + dy * dy);

		return {
			delay: 0,
			duration: Math.sqrt(d) * 120,
			easing: cubicOut,
			css: (t, u) => `transform: translate(${u * dx}px, ${u * dy}px) rotate(${t * 360}deg);`
		};
	}
</script>

{#each list as item, index (item)}
	<div animate:whizz>{item}</div>
{/each}

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

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

App
<script>
	import { cubicOut } from 'svelte/easing';

	/**
	 * @param {HTMLElement} node
	 * @param {{ from: DOMRect; to: DOMRect }} states
	 * @param {any} params
	 */
	function whizz(node, { from, to }, params) {
		const dx = from.left - to.left;
		const dy = from.top - to.top;

		const d = Math.sqrt(dx * dx + dy * dy);

		return {
			delay: 0,
			duration: Math.sqrt(d) * 120,
			easing: cubicOut,
			tick: (t, u) => Object.assign(node.style, { color: t > 0.5 ? 'Pink' : 'Blue' })
		};
	}
</script>

{#each list as item, index (item)}
	<div animate:whizz>{item}</div>
{/each}
<script lang="ts">
	import { cubicOut } from 'svelte/easing';

	function whizz(node: HTMLElement, { from, to }: { from: DOMRect; to: DOMRect }, params: any) {
		const dx = from.left - to.left;
		const dy = from.top - to.top;

		const d = Math.sqrt(dx * dx + dy * dy);

		return {
			delay: 0,
			duration: Math.sqrt(d) * 120,
			easing: cubicOut,
			tick: (t, u) => Object.assign(node.style, { color: t > 0.5 ? 'Pink' : 'Blue' })
		};
	}
</script>

{#each list as item, index (item)}
	<div animate:whizz>{item}</div>
{/each}

在 GitHub 上編輯此頁面

上一頁 下一頁