Skip to main content
Basic Svelte
Introduction
Reactivity
Props
Logic
Events
Bindings
Classes and styles
Actions
Transitions
Advanced Svelte
Advanced reactivity
Reusing content
Motion
Advanced bindings
Advanced transitions
Context API
Special elements
<script module>
Next steps
Basic SvelteKit
Introduction
Routing
Loading data
Headers and cookies
Shared modules
Forms
API routes
$app/state
Errors and redirects
Advanced SvelteKit
Hooks
Page options
Link options
Advanced routing
Advanced loading
Environment variables
Conclusion

Svelte のトランジションエンジンで特に強力な特徴は、トランジションを 遅延 させて複数の要素間でトランジションが調整されるように出来ることです。

このペアのToDoリストを見てみましょう。ToDoを切り替えると反対側のリストに送られます。現実の世界ではオブジェクトはこのような振る舞いをしません。消えたり別の場所に現れたりするのではなく、一連の中間的な位置を移動します。モーションを使用することでアプリで何が起こっているのかをユーザーに理解してもらうことができます。

この効果は、transition.js にあるように、sendreceive というトランジションのペアを作成するcrossfade 関数を使用することで実現できます。要素は、「send」されると、対応する「receive」される要素を探し、その要素を相手の位置に変換してフェードアウトするトランジションを生成します。要素が「receive」されると、逆のことが起こります。対応する要素がない場合は、fallback トランジションが使われます。

TodoList.svelte を開いてください。まず、transition.js から sendreceive をインポートしてください。

TodoList
<script>
	import { send, receive } from './transition.js';

	let { todos, remove } = $props();
</script>
<script lang="ts">
	import { send, receive } from './transition.js';

	let { todos, remove } = $props();
</script>

それから、<li> 要素にもそれらを追加し、todo.id プロパティを、要素にマッチするキーとして使用します。

TodoList
<li
	class={{ done: todo.done }}
	in:receive={{ key: todo.id }}
	out:send={{ key: todo.id }}
>

これでアイテムを切り替えると、アイテムはスムーズに新しい場所に移動します。遷移していない項目は、まだ不器用に跳ね回っています。これは次の章で解決できます。

Edit this page on GitHub

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
62
63
64
65
66
67
68
69
<script>
	import TodoList from './TodoList.svelte';
 
	const todos = $state([
		{ id: 1, done: false, description: 'write some docs' },
		{ id: 2, done: false, description: 'start writing blog post' },
		{ id: 3, done: true, description: 'buy some milk' },
		{ id: 4, done: false, description: 'mow the lawn' },
		{ id: 5, done: false, description: 'feed the turtle' },
		{ id: 6, done: false, description: 'fix some bugs' }
	]);
 
	let uid = todos.length + 1;
 
	function remove(todo) {
		const index = todos.indexOf(todo);
		todos.splice(index, 1);
	}
</script>
 
<div class="board">
	<input
		placeholder="what needs to be done?"
		onkeydown={(e) => {
			if (e.key !== 'Enter') return;
 
			todos.push({
				id: uid++,
				done: false,
				description: e.currentTarget.value
			});
 
			e.currentTarget.value = '';
		}}
	/>
 
	<div class="todo">
		<h2>todo</h2>
		<TodoList todos={todos.filter((t) => !t.done)} {remove} />
	</div>
 
	<div class="done">
		<h2>done</h2>
		<TodoList todos={todos.filter((t) => t.done)} {remove} />
	</div>
</div>
 
<style>
	.board {
		display: grid;
		grid-template-columns: 1fr 1fr;
		grid-column-gap: 1em;
		max-width: 36em;
		margin: 0 auto;
	}
 
	.board > input {
		font-size: 1.4em;
		grid-column: 1/3;
		padding: 0.5em;
		margin: 0 0 1rem 0;
	}
 
	h2 {
		font-size: 2em;
		font-weight: 200;
	}
</style>