1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
import { tweened, type TweenedOptions } from 'svelte/motion'
import { cubicInOut } from 'svelte/easing'
import { interpolate } from 'd3-interpolate'
import type { AnimationFn, Resolve } from './types'
export function signal<TweenValues>(
values: TweenValues,
options: TweenedOptions<TweenValues> = {}
) {
const { subscribe, update, set } = tweened<TweenValues>(values, {
duration: 1000,
easing: cubicInOut,
interpolate,
...options,
})
let tasks: AnimationFn[] = []
function to(
this: any,
values: Partial<TweenValues>,
toOptions: TweenedOptions<TweenValues> = {}
) {
if (typeof values === 'object') {
tasks.push(() => update((prev) => ({ ...prev, ...values }), toOptions))
} else {
tasks.push(() => set(values, toOptions))
}
return this
}
function reset() {
set(values, { duration: 0 })
tasks = []
}
function sfx(this: any, sound: string, { volume = 0.5 } = {}) {
const audio = new Audio(sound)
audio.volume = volume
tasks.push(async () => {
audio
.play()
.catch(() =>
console.error('To play sounds interact with the page first.')
)
})
return this
}
async function then(resolve: Resolve) {
for (const task of tasks) {
await task()
}
resolve()
tasks = []
}
return { subscribe, to, reset, sfx, then }
}
|