Ccmmutty logo
Commutty IT
0 pv9 min read

Svelte学習メモ アニメーション編

https://cdn.magicode.io/media/notebox/084eebcd-a7b7-4b5e-91c1-299de7a2decd.jpeg
こんにちは。
今日も、Svelteの学習をやっていきたいと思います。
今回は、Svelteで用意されているモーション、トランジション、アニメーションについて。

motion

motionは、要素に対して、値を設定することでアニメーションができます。
<script>

	import {Tween } from 'svelte/motion';
	
	const lightness = new Tween(0);
</script>

<style>
	.square {
		width: 100px;
		height: 100px;
		margin-left: 10px;
		}
		
	.container {
		padding-top: 10px;
		width: 120px;
		padding-bottom: 10px;
		background-color: hotpink;
	}
	
</style>


<div class="container">
	<div class="square" style="background: hsl(0, 0%, {lightness.current}%);" ></div>
</div>

<button onclick="{() => lightness.target=100}">白にする</button>
<button onclick="{() => lightness.target=0}">黒にする</button>
これを実行すると、こんな感じ。
白にするを押すと中の黒い四角がふわっと白に。黒にするを押すと、ふわっと黒になります。
わかりやすくするために背景にピンク乗っけてます。
import {Tween } from 'svelte/motion';
Tweenクラスを使用するには、こちらからimportする必要があります。
const lightness = new Tween(0);
こちらのTweenクラスは、Svelte5.8以降使えるようになったようですね。
<div class="square" style="background: hsl(0, 0%, {lightness.current}%);"
currentで現在の値。
<button onclick="{() => lightness.target=100}">白にする</button>
targetを指定することで、値の設定ができるようです。
Tweenの第二引数には、パラメーターが指定できて、
  • durationで、アニメーションの秒数
  • easingで、どういう速度の緩急をつけるか。
を指定できます。
<script>

	import {Tween } from 'svelte/motion';
	import {sineIn} from 'svelte/easing';
	
	const lightness = new Tween(0, {
		duration: 1000,
		easing: sineIn
	});
	
</script>

<style>
	.square {
		width: 100px;
		height: 100px;
		margin-left: 10px;
		}
		
		.container {
			padding-top: 10px;
			width: 120px;
			padding-bottom: 10px;
			background-color: hotpink;
		}
		
</style>


<div class="container">
	<div class="square" style="background: hsl(0, 0%, {lightness.current}%);" ></div>
</div>

<button onclick="{() => lightness.target=100}">白にする</button>
<button onclick="{() => lightness.target=0}">黒にする</button>
easingに指定できるパラメーターとしては、次のもの参照。
実際の動きは、こちらで色々確認できそうです。
イージングの説明については、こちらのnoteがわかりやすかったです。
Spring
こちらは、ばねのような感じにアニメーションさせてくれるようです。
<script>
	import {Spring} from 'svelte/motion';

	const spring = new Spring(0);
	
</script>

<input type="range" bind:value={spring.target} />
<input type="range" bind:value={spring.current} disabled />
実行すると、左のスライダーを動かすと、それに追従するように、右のスライダーがふわっと動いてくれます。
なんかふわっと動くだけで、いい感じです。
Tweenクラスと同様に、targetに値を設定すると、currentがそれに追従してくれるようですね。
const spring = new Spring(0, 
		{
		stiffness: 0.1,
		damping: 0.9
		});
Springクラスでは、stiffness(剛性)と、damping(減衰率)を設定できるっぽい。
  • stiffnessを大きくすると、さっと動いてくれて、小さくすると、少し遅れてついてくる動きに。
  • damping大きくすると、あまり揺れずに動いてくれて、小さくすると、ばねのようにびよびよしながら動いてくれるみたい。
これだけでサクッとアニメーションできるのは便利かも。

transition

transitionは、主に要素の表示・非表示に使うらしい。
<script>

import {fade} from 'svelte/transition';

let isShow = true;

</script>

<button on:click={() => isShow = !isShow}>Toggle</button>

{#if isShow}
	<div transition:fade>hello</div>
{/if}
実行するとこんな感じ。
フェードイン・アウトしてくれます。
<script>

import {fade} from 'svelte/transition';

let isShow = true;

let fadeParams = {
	duration: 1000
}

</script>

<button on:click={() => isShow = !isShow}>Toggle</button>

{#if isShow}
	<div transition:fade={fadeParams}>hello</div>
{/if}
fadeParamsを指定することで、fadeの値を変化させることもできます。
durationは秒数(ミリ秒)です。今回の例だと、1秒かけて、フェードさせています。
fadeParamに指定できるのは、以下のものです。
delay
遅延時間。どれぐらい遅れて表示させるかです。
duration
秒数
easing
イージングの種類です。Tweenのところで出てきましたね。
<script>
	import {fade, fly} from 'svelte/transition';
	
	let isShow = true;

</script>

<button onclick={() => isShow = !isShow}>Toggle</button>

{#if isShow}
	<div in:fade out:fly={{y: 200}}>hello</div>
{/if}
Transitionの表示時と、非表示時のアニメーションを変更することもできます。
<div in:fade out:fly={{y: 200}}>hello</div>
in:で表示の時のアニメーション、outで非表示時のアニメーションを指定できます。
fadeの時と同じようにflyアニメーションにもパラメーターが指定すれば、色々変更できそうです。

クロスフェード

クロスフェードは、二つの要素をなめらかに、入れ替えることができるものです。
<script>

	import {crossfade} from 'svelte/transition';
	
	const [send, receive] = crossfade({ duration: 1000 });
	const key = "test";
	
	let condition = false;
	
</script>

<style>

.container {
	position: relative;
}

.element
{
	position: absolute;
}

</style>

<button onclick="{() => condition = !condition}">クロスフェード</button>

<div class="container">
	{#if condition}
		<strong class="element" in:send={{key}} out:receive={{key}}>太文字</strong>
	{:else}
		<small class="element" in:send={{key}} out:receive={{key}}>小文字</small>
	{/if}

</div>
これを実行すると、こんな感じになめらかに小文字と太文字が切り替わってくれます。
クロスフェードを行うには、
const [send, receive] = crossfade({ duration: 1000 });
sendとreceiveに代入して。 ([]=)って書くのjavascript独特ですね。それぞれ配列に入っているようです。
{#if condition}
		<strong class="element" in:send={{key}} out:receive={{key}}>太文字</strong>
	{:else}
		<small class="element" in:send={{key}} out:receive={{key}}>小文字</small>
このように使うみたいですね。 send, receiveには、同じキー(今回の場合、test)というキーが入ります。
こうすることで、クロスフェードができるようですね。

animation

animationは、主に要素の入れ替えとかに使うらしい。
<script>

	import {flip} from 'svelte/animate';
	
	let items = $state([
		{ id:1, text:"A" },
		{ id:2, text:"B" },
		{ id:3, text:"C" },
	]);
	
	function swapItems(a, b)
	{
		const tmp = items[a];
		items[a] = items[b];
		items[b] = tmp;
	}
	
	function moveUp(index)
	{
		swapItems(index, index-1);
	}
	
	function moveDown(index)
	{
		swapItems(index, index+1);
	}
	
</script>

{#each  items as item, index (item.id) }
	<div animate:flip = {{duration: 200}}>
	{item.text}
	
	<button disabled={index === 0} onclick="{() => moveUp(index)}">上へ</button>
	<button disabled={index === items.length-1} onclick="{() => moveDown(index)}">下へ</button>
	
	</div>
	
{/each}
これを実行するとこんな感じ。
スムーズに、要素の入れ替えができています。
import {flip} from 'svelte/animate';
animationを使うには、一旦importしてやる必要があります。
{#each  items as item, index (item.id) }
(item.id)はタグ解説のところで使用した、keyブロックの役割をしてくれているようです。
要素の入れ替えする時には、keyを指定しないとうまく動作してくれないので、指定してやりましょう。
<div animate:flip = {{duration: 200}}>
要素の入れ替えがあったときに、flipのアニメーションが再生されます。 durationには、秒数を指定しています。

それぞれの使い分け

  • motionは、色を変更したり、値の変更があったときにアニメーションさせる時に使用。
  • transitionは、DOM要素の表示・非表示を切り替える時に。
  • animationは、リストなどで要素を並び替えたり、移動させる時に
使い分けるといいようです。
今日のところはこんな感じで。

Discussion

コメントにはログインが必要です。