Skip to main content

animate:

当带键的 each 块的内容重新排序时,会触发动画。动画不会在元素添加或删除时运行,只会在 each 块内现有数据项的索引发生变化时运行。animate 指令必须在带键的 each 块的直接子元素上使用。

动画可以与 Svelte 的内置动画函数或自定义动画函数一起使用。

<!-- 当 `list` 重新排序时动画将会运行 -->
{#each list as item, index (item)}
	<li animate:flip>{item}</li>
{/each}

动画参数

与 actions 和过渡一样,动画也可以有参数。

(双重 {{大括号}} 不是特殊语法;这是表达式标签内的对象字面量。)

{#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 参数是一个包含 from 和 to 属性的对象,每个属性都包含一个 DOMRect,描述元素在其 开始 和 结束 位置的几何形状。

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,那就尽可能使用 css — 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 编辑此页面

上一页 下一页