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>;