iT邦幫忙

2024 iThome 鐵人賽

DAY 11
0
Modern Web

Svelte 的奇妙冒險系列 第 11

[Svelte 的奇妙冒險] Day 11 - motion 與 transition

  • 分享至 

  • xImage
  •  

Svelte 內建了蠻多非常方便的動畫 module ,讓我們可以簡單地做出還不錯的動畫效果,至少以我工作場景中所需要的動畫應該都能完美解決,今天我們一樣以這幾天的 Todo List 作為基底來添加動畫。

先打個預防針,因為我工作以來主要都是做後台網頁所以即使有動畫也不會是非常炫砲的需求。

motion

svelte/motion 的這個 module 中有 tweenedspring 這兩個 function 。

而 motion 的主要功用就是幫我們產生出一個 writable store ,然後在每次變更時會幫我們生成中間的值。

直接來看例子,以下是我將打字長度加上 tweened 所生成的效果:

會發現每次數字的增長,都不是直接 +1 而是把 +1 這個過程變得更絲滑了。

所以我現在就來實做一個功能就是限制 Input 的最大長度,但用 progress 來提示使用者。

<!-- in Input.svelte -->
<script lang="ts">
	import { tweened } from 'svelte/motion';
	import { linear } from 'svelte/easing';

	interface InputProps {
		label: string;
		value: string;
		maxLength?: number;
	}
  
	let { label, value = $bindable(), maxLength }: InputProps = $props();
	const size = tweened(0, {
		duration: 400,
		easing: linear
	});
	$effect(() => {
		size.set(value.length);
	});
</script>

首先會看到 tweened() 這個 function ,它的第一個參數是預設值,第二個是這個動畫效果的設定,duration 指的就是每次動畫要執行多少毫秒,easing 就是所謂的速度曲線,也就是速度與時間的關係,舉例來說線性變化就是從頭到尾動畫的速度都一樣,那們這邊先拿內建的 linear 來看一下線性的速度曲線長得如何。

應該會覺得十分無聊吧?所以通常動畫都不會是用線性的速度曲線,這邊我們隨便拿一個內建的

bounceOut

會覺得好看了不少吧? Svelte 還內建了許多 easing ,可以參考這裡

transition

就是所謂的轉場,在 Svelte 中會在元素掛載到 DOM 上時或者移除時會觸發 transition ,那我們就用新增和移除 Todo 卡片來試試看 transition 吧

<script lang="ts">
    import { fly } from 'svelte/transition';

    //以下省略
</script>


{#snippet card(todo: Todo)}
	<div class="card shadow bg-base-200 mb-4" transition:fly>
		<div class="card-body">
			<div class="flex justify-between items-center">
				<h2 class:line-through={todo.done} class="card-title">{todo.title}</h2>
				<input type="checkbox" bind:checked={todo.done} class="checkbox checkbox-lg" />
			</div>
			<p class:text-gray-700={todo.done}>{todo.content}</p>
			<button class="ml-auto w-20 btn btn-error" onclick={() => removeTodo(todo.id)}>
				Remove
			</button>
		</div>
	</div>
{/snippet}

 <!-- 以下省略 -->

在 Svelte 中是用 transition: directive 來控制的,這裡我們就先用 fly 這個 transition 效果來試試看,預設情況下會是長這樣的:

fly 有許多可以設定的參數,在預設情況下會是這樣:

transition:fly={{ y: 0, x: 0, easing: cubicOut, opacity: 0 }}

xy 指的是以元素掛載到 DOM 上的那個點作為原點,轉場開始/結束的地方相對於原點的垂直及水平的 offset,那 easing 就跟我們上面提到速度曲線是一樣的,opacity 是指開始/結束時的透明度是多少。

我們先以 transition:fly={{ y: 200 }} 試試看,也代表是 transition 過程是:掛載是從 (0,-200) → (0,0) 的位置,移除時就是從 (0,0) → (0,-200)。

offset 的值當傳入 number 時,就是指 px 數

但有時候就是不想要讓掛載跟移除用一樣的 transition,這時我們可以改成這樣

 in:fly={{ y: 200 }} out:fly={{ y: -200 }}

也就是代表掛載到 DOM 時是從 (0,-200) → (0,0) ,移除時是從 (0,0) → (0,200)

除了 fly 以外還有許多 transition 可以使用,每個 transition 參數能接受的參數也不太相同,有興趣的讀者可以參考官方文件的介紹。


今天只是簡單地玩一下 Svelte 的 motion 與 transition,其中他們應該還有蠻多可以深掘的地方,只是我對於動畫效果並沒有研究太深,所以只能這樣簡單的演示。

但光是這樣我就覺得 Svelte 這點真的蠻方便的,至少對於我這種不喜歡手刻動畫的開發者來說真的是非常非常友善。

參考資料

source code

https://github.com/toddLiao469469/30days-for-svelte5/tree/day11/src/routes/todo-list


上一篇
[Svelte 的奇妙冒險] Day 10 - 先寫一個最陽春的 Todo list (2)
下一篇
[Svelte 的奇妙冒險] Day 12 - global state management
系列文
Svelte 的奇妙冒險30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言