メインコンテンツへスキップ

transition

遷移は、状態の変化の結果として要素がDOMに出入りする際にトリガーされます。

ブロック(例:{#if ...} ブロック)がアウト遷移している場合、その中のすべての要素(独自の遷移を持たない要素も含む)は、ブロック内のすべての遷移が完了するまでDOMに残ります。

transition: ディレクティブは、双方向の遷移を示しています。これは、遷移が進行中でもスムーズに反転できることを意味します。

<script>
	import { fade } from 'svelte/transition';

	let visible = $state(false);
</script>

<button onclick={() => visible = !visible}>toggle</button>

{#if visible}
	<div transition:fade>fades in and out</div>
{/if}

ビルトイン遷移

svelte/transition モジュールからインポートできる、ビルトイン遷移の選択肢があります。

ローカル vs グローバル

遷移はデフォルトでローカルです。ローカル遷移は、所属するブロックの作成または破棄時のみ再生され、親ブロックの作成または破棄時には再生されません。

{#if x}
	{#if y}
		<p transition:fade>fades in and out only when y changes</p>

		<p transition:fade|global>fades in and out when x or y change</p>
	{/if}
{/if}

遷移パラメータ

遷移にはパラメータを設定できます。

(二重の中括弧{{curlies}}は特別な構文ではありません。これは式タグ内のオブジェクトリテラルです。)

{#if visible}
	<div transition:fade={{ duration: 2000 }}>fades in and out over two seconds</div>
{/if}

カスタム遷移関数

transition = (node: HTMLElementnode: HTMLElement, params: anyparams: any, 
options: {
    direction: "in" | "out" | "both";
}
options
: { direction: "in" | "out" | "both"direction: 'in' | 'out' | 'both' }) => {
delay?: number, duration?: number, easing?: (t: numbert: number) => number, css?: (t: numbert: number, u: numberu: number) => string, tick?: (t: numbert: number, u: numberu: number) => void }

遷移はカスタム関数を使用できます。返されたオブジェクトにcss関数が含まれている場合、Svelteはウェブアニメーションのkeyframesを生成します。

cssに渡されるt引数は、easing関数が適用された後の0から1の間の値です。イン遷移は0から1アウト遷移は1から0を実行します。言い換えれば、1は遷移が適用されていないかのように、要素の自然な状態です。u引数は1 - tと等しくなります。

関数は、異なるtu引数で、遷移が始まるに繰り返し呼び出されます。

アプリ
<script>
	import { elasticOut } from 'svelte/easing';

	/** @type {boolean} */
	export let visible;

	/**
	 * @param {HTMLElement} node
	 * @param {{ delay?: number, duration?: number, easing?: (t: number) => number }} params
	 */
	function whoosh(node, params) {
		const existingTransform = getComputedStyle(node).transform.replace('none', '');

		return {
			delay: params.delay || 0,
			duration: params.duration || 400,
			easing: params.easing || elasticOut,
			css: (t, u) => `transform: ${existingTransform} scale(${t})`
		};
	}
</script>

{#if visible}
	<div in:whoosh>whooshes in</div>
{/if}
<script lang="ts">
	import { elasticOut } from 'svelte/easing';

	export let visible: boolean;

	function whoosh(node: HTMLElement, params: { delay?: number, duration?: number, easing?: (t: number) => number }) {
		const existingTransform = getComputedStyle(node).transform.replace('none', '');

		return {
			delay: params.delay || 0,
			duration: params.duration || 400,
			easing: params.easing || elasticOut,
			css: (t, u) => `transform: ${existingTransform} scale(${t})`
		};
	}
</script>

{#if visible}
	<div in:whoosh>whooshes in</div>
{/if}

カスタム遷移関数は、同じtu引数を使用して遷移中に呼び出されるtick関数を返すこともできます。

tickではなくcssを使用できる場合は、そうしてください。ウェブアニメーションはメインスレッドから離れて実行できるため、低速なデバイスでのジャンクを防ぐことができます。

アプリ
<script>
	export let visible = false;

	/**
	 * @param {HTMLElement} node
	 * @param {{ speed?: number }} params
	 */
	function typewriter(node, { speed = 1 }) {
		const valid = node.childNodes.length === 1 && node.childNodes[0].nodeType === Node.TEXT_NODE;

		if (!valid) {
			throw new Error(`This transition only works on elements with a single text node child`);
		}

		const text = node.textContent;
		const duration = text.length / (speed * 0.01);

		return {
			duration,
			tick: (t) => {
				const i = ~~(text.length * t);
				node.textContent = text.slice(0, i);
			}
		};
	}
</script>

{#if visible}
	<p in:typewriter={{ speed: 1 }}>The quick brown fox jumps over the lazy dog</p>
{/if}
<script lang="ts">
	export let visible = false;

	function typewriter(node: HTMLElement, { speed = 1 }: { speed?: number }) {
		const valid = node.childNodes.length === 1 && node.childNodes[0].nodeType === Node.TEXT_NODE;

		if (!valid) {
			throw new Error(`This transition only works on elements with a single text node child`);
		}

		const text = node.textContent;
		const duration = text.length / (speed * 0.01);

		return {
			duration,
			tick: (t) => {
				const i = ~~(text.length * t);
				node.textContent = text.slice(0, i);
			}
		};
	}
</script>

{#if visible}
	<p in:typewriter={{ speed: 1 }}>The quick brown fox jumps over the lazy dog</p>
{/if}

遷移が遷移オブジェクトではなく関数を返す場合、関数は次のマイクロタスクで呼び出されます。これにより、複数の遷移を調整し、クロスフェード効果を可能にします。

遷移関数には、遷移に関する情報を含む3番目の引数optionsも渡されます。

optionsオブジェクトで使用可能な値は

  • direction - 遷移の種類に応じてinout、またはbothのいずれか

遷移イベント

遷移を持つ要素は、標準的なDOMイベントに加えて、次のイベントをディスパッチします。

  • introstart
  • introend
  • outrostart
  • outroend
{#if visible}
	<p
		transition:fly={{ y: 200, duration: 2000 }}
		onintrostart={() => (status = 'intro started')}
		onoutrostart={() => (status = 'outro started')}
		onintroend={() => (status = 'intro ended')}
		onoutroend={() => (status = 'outro ended')}
	>
		Flies in and out
	</p>
{/if}

GitHubでこのページを編集する

前へ 次へ