iT邦幫忙

2023 iThome 鐵人賽

DAY 27
0
Modern Web

了不起的 Svelte系列 第 27

第 27 天:Svelte 的過場:`transition`

  • 分享至 

  • xImage
  •  

第 27 天:Svelte 的過場:transition

第 27 天要講的事

  1. 替 HTML 元素加入過場效果
  2. 過場效果的參數
  3. 載入跟卸載時的過場

  昨天我們利用 Svelte 提供的 Store 物件,在色票產生器的專案當中實作出了 toast 的效果,當使用者在色票產生器當中點選【色票加一】、【色票減一】、【鎖定色票】、【解鎖色票】等操作時,就會跳出相對應的 toast 提示使用者。看起來互動效果是不是很不錯呢。知道還有什麼更不錯的嗎?就是替我們的 toast 加入過場效果。

替 HTML 元素加入過場效果

  還記得 Svelte 的設計是藉由編譯器,將我們撰寫的 Svelte 檔案轉化為純純的 Javascript,藉此做出具有互動 (reactive) 能力的前端介面。也正是因為編譯器的緣故,開發者在撰寫專案程式碼時,可以寫得簡潔又乾淨,編譯器仍然可以幫我們輸出成互動 (reactive) 詳盡又效能突出 (effective) 的成品。除此之外,Svelte 還提供了一項福利,那就是透過編譯器幫我們做出漂亮的過場效果。
  程式碼的撰寫方式也很簡單,話不多說,讓我們直接來 Svelte REPL (Read-Eval-Print-Loop) 寫寫看:

<script>
  import { fade } from 'svelte/transition';
  let checked = true;
</script>

<label>
  <input type="checkbox" bind:checked />
  visible
</label>

{#if checked}
  <p transition:fade>
    Fades in and out
  </p>
{/if}
  • 第二行:import { fade } from 'svelte/transition';
      引入我們需要的函式 fade

  • 第七行:<input type="checkbox" bind:checked />
      用 bind:checked 資料綁定的方式,只要點擊這個 checkbox,就可以直接將 checked 的值在 truefalse 之間切換。

  • 第十一行:{#if checked}
      如果 checkedtrue,就會顯示以下段落。更精確一點來說,是會掛載以下的 HTML 元素到 DOM 當中。否則,就會將該 HTML 元素從 DOM 當中卸載。

  • 第十二行:<p transition:fade>
      替我們在掛載/卸載之間切換的 HTML 元素加上 transition:fade 這一個屬性。看到 : 應該就知道這是 Svelte 所提供的特殊功能,用來處理 transition,也就是過場效果。而我們選用的過場效果是 fade。過場效果觸發的時機點是 HTML 元素從 DOM 當中掛載/卸載的那個瞬間。所以當我們將 checkedfalse 切換成 true,或是從 true 切換成 false,就會啟動過場的效果。

https://i.ibb.co/g4kvNwP/27.gif
圖一、我淡出了!我又淡入了!我又淡出了!我又又淡入了!

  除了 fade 之外,還有其他簡易的過場效果可以選擇,包括模糊 blur、飛入 fly、翻動 slide、縮放 scale、繪畫 draw 等等。有興趣的可以參考 Svelte 官方文件做更進一步的認識。
  由於 toast 是隨著使用者在互動介面上操作而跳出來的提示,所以相當適合加上一個過場效果來營造出提示的感覺。就讓我們試著在專案當中練習看看如何使用 Svelte 的過場效果吧。直接來到需要過場效果的 Toast.svelte

/src/lib/Toast.svelte
<script>
  import { scale } from "svelte/transition";
  import { toastStore } from "./toastStore";
  import plus from "../assets/plus.svg";
  import minus from "../assets/minus.svg";
  import lock from "../assets/lock.svg";
  import unlock from "../assets/unlock.svg";
  export let toast;

  const icons = { plus, minus, lock, unlock };
  $: icon = icons[toast.action];
</script>

<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-static-element-interactions -->
<div
  class="toast"
  on:click={() => toastStore.removeToast({ id: toast.id })}
  transition:scale
>
  <div class="icon">
    <img src={icon} alt={toast.action} />
  </div>
  <div class="hex" style="color: #{toast.hex}">{toast.hex}</div>
</div>
  • 第二行:import { scale } from "svelte/transition";
      剛才已經看過 fade,這次換引入 scale 來玩玩。

  • 第十八行:transition:scale
      在我們想要加入過場效果的 HTML 元素 <div class="toast"> 當中多寫一段 transition:scale,這樣就算設定完成囉!

https://i.ibb.co/hVjr886/27.gif
圖二、Q 彈的 toast

過場效果的參數

  有了過場效果還不夠,我們還可以加入一些參數去調整過場效果的表現方式,讓過場效果符合不同專案的不同需求:

/src/lib/Toast.svelte
<script>
  import { scale } from "svelte/transition";
  import { elasticInOut } from "svelte/easing";
  import { toastStore } from "./toastStore";
  import plus from "../assets/plus.svg";
  import minus from "../assets/minus.svg";
  import lock from "../assets/lock.svg";
  import unlock from "../assets/unlock.svg";
  export let toast;

  const icons = { plus, minus, lock, unlock };
  $: icon = icons[toast.action];
</script>

<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-static-element-interactions -->
<div
  class="toast"
  on:click={() => toastStore.removeToast({ id: toast.id })}
  transition:scale={{ easing: elasticInOut }}
>
  <div class="icon">
    <img src={icon} alt={toast.action} />
  </div>
  <div class="hex" style="color: #{toast.hex}">{toast.hex}</div>
</div>
  • 第三行:import { elasticInOut } from "svelte/easing";
      除了 scale 這個處理過場效果的函式之外,再引入一個變化相關 (easing) 的函式 elasticInOut。Svelte 同樣也提供了不少變化相關的函式,有興趣的可以參考 Svelte 官方文件做更進一步的認識。

  • 第十九行:transition:scale={{ easing: elasticInOut }}
      先用大括弧 {} 開啟一個 Javascript 的領域,接著放入一個 Javascript 物件當作 scale 這個函式的參數,用來調整 scale 的表現。不同的過場效果函式可以使用的參數也稍微有所不同,一般通用的參數包括有延遲開始的時間 delay、效果持續時間 duration、變化函式 easing 等等,更多的參數可以參考 Svelte 官方文件。

https://i.ibb.co/6brVp5c/27.gif
圖三、更加 Q 彈的 Toast

載入跟卸載時的過場

  過場效果發生的時機包括 HTML 元素載入 DOM 的時候,以及 HTML 元素從 DOM 卸載的時候。如果這兩種不同的時間點想要採用不同的過場效果,可以嗎?Svelte 覺得沒問題!

/src/lib/Toast.svelte
<script>
  import { scale, fade } from "svelte/transition";
  import { elasticInOut } from "svelte/easing";
  import { toastStore } from "./toastStore";
  import plus from "../assets/plus.svg";
  import minus from "../assets/minus.svg";
  import lock from "../assets/lock.svg";
  import unlock from "../assets/unlock.svg";
  export let toast;

  const icons = { plus, minus, lock, unlock };
  $: icon = icons[toast.action];
</script>

<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-static-element-interactions -->
<div
  class="toast"
  on:click={() => toastStore.removeToast({ id: toast.id })}
  in:scale={{ easing: elasticInOut }}
  out:fade
>
  <div class="icon">
    <img src={icon} alt={toast.action} />
  </div>
  <div class="hex" style="color: #{toast.hex}">{toast.hex}</div>
</div>
  • 第二行:import { scale, fade } from "svelte/transition";
      除了原本的 scale,再引入一個過場效果的函式 fade

  • 第十九行:in:scale={{ easing: elasticInOut }}
      將原本的 transition:scale 改成 in:scale,表示我們想要在 HTML 元件掛載到 DOM 時使用 scale 這個過場效果。

  • 第二十行:out:fade
      並解加上新的功能 out:fade,表示我們想要在 HTML 元件從 DOM 當中卸載時使用 fade 這個過場效果。

https://i.ibb.co/xSsXJBS/27.gif
圖四、Q 彈的 toast,淡出的退場

  這就是我們今天關於 Svelte 過場效果的內容了,謝謝大家。


上一篇
第 26 天:Svelte 的互動百寶箱:Store(三)
下一篇
第 28 天:Svelte 的動態效果:`tweened`
系列文
了不起的 Svelte30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言