aboutsummaryrefslogtreecommitdiff
path: root/src/lib/motion
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/motion')
-rw-r--r--src/lib/motion/index.ts4
-rw-r--r--src/lib/motion/signal.ts61
-rw-r--r--src/lib/motion/types.ts2
-rw-r--r--src/lib/motion/utils.ts10
4 files changed, 77 insertions, 0 deletions
diff --git a/src/lib/motion/index.ts b/src/lib/motion/index.ts
new file mode 100644
index 0000000..79e3d36
--- /dev/null
+++ b/src/lib/motion/index.ts
@@ -0,0 +1,4 @@
+import { signal } from './signal'
+import { animate, all } from './utils'
+
+export { signal, animate, all }
diff --git a/src/lib/motion/signal.ts b/src/lib/motion/signal.ts
new file mode 100644
index 0000000..99697ce
--- /dev/null
+++ b/src/lib/motion/signal.ts
@@ -0,0 +1,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 }
+}
diff --git a/src/lib/motion/types.ts b/src/lib/motion/types.ts
new file mode 100644
index 0000000..e97a109
--- /dev/null
+++ b/src/lib/motion/types.ts
@@ -0,0 +1,2 @@
+export type AnimationFn = () => Promise<void>
+export type Resolve = (value?: any) => Promise<void>
diff --git a/src/lib/motion/utils.ts b/src/lib/motion/utils.ts
new file mode 100644
index 0000000..a81c02e
--- /dev/null
+++ b/src/lib/motion/utils.ts
@@ -0,0 +1,10 @@
+import { onMount } from 'svelte'
+import type { AnimationFn } from './types'
+
+export function animate(fn: AnimationFn) {
+ onMount(fn)
+}
+
+export function all(...animations: AnimationFn[]) {
+ return Promise.all(animations)
+}