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: HTMLElement
node: HTMLElement, { from: any
from: type DOMRect: any
DOMRect, to: any
to: type DOMRect: any
DOMRect } , params: any
params: any) => {
delay?: number,
duration?: number,
easing?: (t: number
t: number) => number,
css?: (t: number
t: number, u: number
u: number) => string,
tick?: (t: number
t: number, u: number
u: number) => void
}
動畫可以使用自訂函式,這些函式會提供 node
、一個 animation
物件以及任何 parameters
作為參數。animation
參數是一個物件,包含 from
和 to
屬性,每個屬性都包含一個 DOMRect,描述元素在 start
和 end
位置的幾何形狀。from
屬性是元素在其起始位置的 DOMRect,而 to
屬性是元素在清單重新排序且 DOM 更新後在其最終位置的 DOMRect。
如果回傳的物件具有 css
方法,Svelte 將建立一個在元素上播放的 web 動畫。
傳遞給 css
的 t
參數是一個值,在套用 easing
函式後,該值會從 0
變為 1
。u
參數等於 1 - t
。
該函式在動畫開始之前會重複呼叫,使用不同的 t
和 u
參數。
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
函式,該函式會在動畫期間使用相同的 t
和 u
參數呼叫。
如果可以使用
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}