svelte/motion 模块导出了两个函数:tweened 和 spring,用于创建可写存储,这些存储的值在 set 和 update 之后随时间变化,而不是立即变化。
tweened
function tweened<T>(value?: T | undefined,defaults?: TweenedOptions<T> | undefined): Tweened<T>;
Tweened 存储会在固定持续时间内更新它们的值。以下是可用的选项:
delay(number,默认为 0)— 开始之前的毫秒数duration(number|function,默认为 400)— tween 持续的毫秒数easing(function,默认为t => t)— 一个 easing 函数interpolate(function)— 见下文
store.set 和 store.update 可以接受第二个 options 参数,该参数将覆盖在实例化时传入的选项。
两个函数都返回一个 Promise,当 tween 完成时解决。如果 tween 被中断,promise 将永远不会解决。
Svelte 可以开箱即用地在两个数字、两个数组或两个对象(只要数组和对象的形状相同,它们的“叶子”属性也是数字)之间进行插值。
<script>import { tweened } from 'svelte/motion';import { cubicOut } from 'svelte/easing';const size = tweened(1, {duration: 300,easing: cubicOut});function handleClick() {// 这等同于 size.update(n => n + 1)$size += 1;}</script><button on:click={handleClick} style="transform: scale({$size}); transform-origin: 0 0">embiggen</button>
如果初始值为 undefined 或 null,则第一次值更改将立即生效。这在你有基于 props 的 tweened 值,并且不希望在组件首次渲染时有任何运动时非常有用。
import { tweened } from 'svelte/motion';import { cubicOut } from 'svelte/easing';const size = tweened(undefined, {duration: 300,easing: cubicOut});$: $size = big ? 100 : 10;
interpolate 选项允许你在 任何 任意值之间进行 tween。它必须是一个 (a, b) => t => value 函数,其中 a 是起始值,b 是目标值,t 是 0 到 1 之间的数字,value 是结果。例如,我们可以使用 d3-interpolate 包在两种颜色之间平滑插值。
<script>import { interpolateLab } from 'd3-interpolate';import { tweened } from 'svelte/motion';const colors = ['rgb(255, 62, 0)', 'rgb(64, 179, 255)', 'rgb(103, 103, 120)'];const color = tweened(colors[0], {duration: 800,interpolate: interpolateLab});</script>{#each colors as c}<button style="background-color: {c}; color: white; border: none;" on:click={(e) => color.set(c)}>{c}</button>{/each}<h1 style="color: {$color}">{$color}</h1>
spring
function spring<T = any>(value?: T | undefined,opts?: SpringOpts | undefined): Spring<T>;
spring 存储根据其 stiffness 和 damping 参数逐渐变为其目标值。与 tweened 存储在固定持续时间内更改其值不同,spring 存储的更改时间由其现有速度决定,允许在许多情况下更自然地运动。以下是可用的选项:
stiffness(number,默认为0.15)— 0 到 1 之间的值,数值越高意味着 ‘更紧’ 的弹簧damping(number,默认为0.8)— 0 到 1 之间的值,数值越低意味着 ‘更有弹性’ 的弹簧precision(number,默认为0.01)— 确定弹簧被认为 ‘稳定’ 的阈值,数值越低意味着更精确
上述所有选项都可以在弹簧运动时更改,并会立即生效。
import { spring } from 'svelte/motion';const size = spring(100);size.stiffness = 0.3;size.damping = 0.4;size.precision = 0.005;
与 tweened 存储一样,set 和 update 返回一个 Promise,如果弹簧稳定则解决。
set 和 update 都可以接受第二个参数 —— 一个具有 hard 或 soft 属性的对象。{ hard: true } 立即设置目标值;{ soft: n } 在 n 秒内保留现有动量然后稳定。{ soft: true } 等同于 { soft: 0.5 }。
import { spring } from 'svelte/motion';const coords = spring({ x: 50, y: 50 });// 立即更新值coords.set({ x: 100, y: 200 }, { hard: true });// 保留 1s 的现有动量coords.update((target_coords, coords) => {return { x: target_coords.x, y: coords.y };},{ soft: 1 });
<script>import { spring } from 'svelte/motion';const coords = spring({ x: 50, y: 50 },{stiffness: 0.1,damping: 0.25});</script>
如果初始值是 undefined 或 null,第一次值更改将立即生效,就像 tweened 值一样(见上文)。
import { spring } from 'svelte/motion';const size = spring();$: $size = big ? 100 : 10;
类型
Spring
interface Spring<T> extends Readable<T> {…}
set: (new_value: T, opts?: SpringUpdateOpts) => Promise<void>;
update: (fn: Updater<T>, opts?: SpringUpdateOpts) => Promise<void>;
precision: number;
damping: number;
stiffness: number;
Tweened
interface Tweened<T> extends Readable<T> {…}
set(value: T, opts?: TweenedOptions<T>): Promise<void>;
update(updater: Updater<T>, opts?: TweenedOptions<T>): Promise<void>;
