Skip to content

Commit 0b27a96

Browse files
authored
Motion tutorials (#949)
* update tween exercise * update spring tutorial
1 parent b0165dd commit 0b27a96

File tree

17 files changed

+177
-132
lines changed

17 files changed

+177
-132
lines changed
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: Introducing stores
2+
title: Stores
33
---
44

55
Prior to the introduction of runes in Svelte 5, stores were the idiomatic way to handle reactive state outside components. That's no longer the case, but you'll still encounter stores when using Svelte (including in SvelteKit, for now), so it's worth knowing how to use them.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<script>
2+
let progress = $state(0);
3+
</script>
4+
5+
<progress value={progress}></progress>
6+
7+
<button onclick={() => (progress = 0)}>
8+
0%
9+
</button>
10+
11+
<button onclick={() => (progress = 0.25)}>
12+
25%
13+
</button>
14+
15+
<button onclick={() => (progress = 0.5)}>
16+
50%
17+
</button>
18+
19+
<button onclick={() => (progress = 0.75)}>
20+
75%
21+
</button>
22+
23+
<button onclick={() => (progress = 1)}>
24+
100%
25+
</button>
26+
27+
<style>
28+
progress {
29+
display: block;
30+
width: 100%;
31+
}
32+
</style>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<script>
2+
import { Tween } from 'svelte/motion';
3+
import { cubicOut } from 'svelte/easing';
4+
5+
let progress = new Tween(0, {
6+
duration: 400,
7+
easing: cubicOut
8+
});
9+
</script>
10+
11+
<progress value={progress.current}></progress>
12+
13+
<button onclick={() => (progress.target = 0)}>
14+
0%
15+
</button>
16+
17+
<button onclick={() => (progress.target = 0.25)}>
18+
25%
19+
</button>
20+
21+
<button onclick={() => (progress.target = 0.5)}>
22+
50%
23+
</button>
24+
25+
<button onclick={() => (progress.target = 0.75)}>
26+
75%
27+
</button>
28+
29+
<button onclick={() => (progress.target = 1)}>
30+
100%
31+
</button>
32+
33+
<style>
34+
progress {
35+
display: block;
36+
width: 100%;
37+
}
38+
</style>

apps/svelte.dev/content/tutorial/02-advanced-svelte/03-stores/02-tweens/index.md renamed to apps/svelte.dev/content/tutorial/02-advanced-svelte/03-motion/01-tweens/index.md

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,53 @@
22
title: Tweened values
33
---
44

5-
Alongside the `writable` and `readable` stores, Svelte ships stores for adding motion to your user interfaces.
5+
Often, a good way to communicate that a value is changing is to use _motion_. Svelte ships classes for adding motion to your user interfaces.
66

7-
Let's start by changing the `progress` store to a `tweened` store:
7+
Import the `Tween` class from `svelte/motion`:
88

99
```svelte
1010
/// file: App.svelte
1111
<script>
12-
import { +++tweened+++ } from 'svelte/+++motion+++';
12+
+++import { Tween } from 'svelte/motion';+++
1313
14-
const progress = +++tweened+++(0);
14+
let progress = $state(0);
1515
</script>
1616
```
1717

18+
Turn `progress` into an instance of `Tween`:
19+
20+
```svelte
21+
/// file: App.svelte
22+
<script>
23+
import { Tween } from 'svelte/motion';
24+
25+
let progress = +++new Tween+++(0);
26+
</script>
27+
```
28+
29+
The `Tween` class has a writable `target` property and a readonly `current` property — update the `<progress>` element...
30+
31+
```svelte
32+
<progress value={progress.+++current+++}></progress>
33+
```
34+
35+
...and each of the event handlers:
36+
37+
```svelte
38+
<button onclick={() => (progress.+++target+++ = 0)}>
39+
0%
40+
</button>
41+
```
42+
1843
Clicking the buttons causes the progress bar to animate to its new value. It's a bit robotic and unsatisfying though. We need to add an easing function:
1944

2045
```svelte
2146
/// file: App.svelte
2247
<script>
23-
import { tweened } from 'svelte/motion';
48+
import { Tween } from 'svelte/motion';
2449
+++import { cubicOut } from 'svelte/easing';+++
2550
26-
const progress = tweened(0, +++{
51+
let progress = new Tween(0, +++{
2752
duration: 400,
2853
easing: cubicOut
2954
}+++);
@@ -32,11 +57,11 @@ Clicking the buttons causes the progress bar to animate to its new value. It's a
3257

3358
> [!NOTE] The `svelte/easing` module contains the [Penner easing equations](https://web.archive.org/web/20190805215728/http://robertpenner.com/easing/), or you can supply your own `p => t` function where `p` and `t` are both values between 0 and 1.
3459
35-
The full set of options available to `tweened`:
60+
The full set of options available to `Tween`:
3661

3762
- `delay` — milliseconds before the tween starts
3863
- `duration` — either the duration of the tween in milliseconds, or a `(from, to) => milliseconds` function allowing you to (e.g.) specify longer tweens for larger changes in value
3964
- `easing` — a `p => t` function
4065
- `interpolate` — a custom `(from, to) => t => value` function for interpolating between arbitrary values. By default, Svelte will interpolate between numbers, dates, and identically-shaped arrays and objects (as long as they only contain numbers and dates or other valid arrays and objects). If you want to interpolate (for example) colour strings or transformation matrices, supply a custom interpolator
4166

42-
You can also pass these options to `progress.set` and `progress.update` as a second argument, in which case they will override the defaults. The `set` and `update` methods both return a promise that resolves when the tween completes.
67+
You can also call `progress.set(value, options)` instead of assigning directly to `progress.target`, in which case `options` will override the defaults. The `set` method returns a promise that resolves when the tween completes.
Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,21 @@
11
<script>
2-
import { writable } from 'svelte/store';
3-
4-
let coords = writable({ x: 50, y: 50 });
5-
let size = writable(10);
2+
let coords = $state({ x: 50, y: 50 });
3+
let size = $state(10);
64
</script>
75

86
<svg
97
onmousemove={(e) => {
10-
coords.set({ x: e.clientX, y: e.clientY });
8+
coords = { x: e.clientX, y: e.clientY };
119
}}
12-
onmousedown={() => size.set(30)}
13-
onmouseup={() => size.set(10)}
10+
onmousedown={() => (size = 30)}
11+
onmouseup={() => (size = 10)}
1412
role="presentation"
1513
>
1614
<circle
17-
cx={$coords.x}
18-
cy={$coords.y}
19-
r={$size}
20-
/>
15+
cx={coords.x}
16+
cy={coords.y}
17+
r={size}
18+
></circle>
2119
</svg>
2220

2321
<div class="controls">

0 commit comments

Comments
 (0)