特效轉場 transition
效果酷炫、風格強烈的 Transition 元件!◝( •ω• )◟
注意!
此元件會占用 style
之 filter
屬性,請確保沒有使用 filter
,否則會導致原本的 filter
效果消失。ლ(╹◡╹ლ)
使用範例
基本用法
用法與 Vue 內建的 Transition 元件相同。
(點擊後開始轉場)
WAVE
CYBERPSYCHOSIS
MELT
GLITCH
ERODE
查看範例原始碼
vue
<template>
<div class="w-full flex flex-col gap-4 border border-gray-300 p-6">
<div class="flex flex-col items-center justify-center gap-3">
<div
v-for="item in list"
:key="item.name"
class="item h-[5rem] w-full flex items-center justify-center"
@click="item.visible = !item.visible"
>
<transition-special-effects
:enter="item.name"
:leave="item.name"
>
<div
v-if="item.visible"
class="px-8 py-2"
:class="item.class"
>
{{ item.name.toUpperCase() }}
</div>
</transition-special-effects>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import type { TransitionName } from '../type'
import { ref } from 'vue'
import TransitionSpecialEffects from '../transition-special-effects.vue'
const list = ref<Array<{
visible: boolean;
name: `${TransitionName}`;
class: string;
}>>([{
visible: true,
name: 'wave',
class: 'bg-blue-200 text-blue-900 text-2xl font-bold rounded-full',
}, {
visible: true,
name: 'cyberpsychosis',
class: 'bg-gray-200 text-gray-900 text-2xl font-bold',
}, {
visible: true,
name: 'melt',
class: 'text-gray-400 border-2 border-gray-200 text-3xl rounded-xl font-bold',
}, {
visible: true,
name: 'glitch',
class: 'text-red-800 border-dashed border border-red-800 text-2xl font-bold',
}, {
visible: true,
name: 'erode',
class: 'bg-[#222] text-white text-2xl font-black tracking-widest',
}])
</script>
<style scoped lang="sass">
.item
cursor: pointer
transition-duration: 0.5s
</style>
進入與離開
可以分別指定 enter 與 leave 特效。
進入特效
離開特效
鱈魚 Codfish
困擾買不到 IP69K 等級的防水電腦 ( ´•̥̥̥ ω •̥̥̥` )
查看範例原始碼
vue
<template>
<div class="w-full flex flex-col gap-4 border border-gray-300 p-6">
<div class="flex flex-col gap-4 border rounded py-4">
<div class="flex items-center gap-1 px-4">
<div class="w-20">
進入特效
</div>
<div class="flex-1 border rounded">
<select
v-model="enterName"
class="w-full p-2"
>
<option
v-for="option in options"
:key="option"
:value="option"
>
{{ option }}
</option>
</select>
</div>
</div>
<div class="flex items-center gap-1 px-4">
<div class="w-20">
離開特效
</div>
<div class="flex-1 border rounded">
<select
v-model="leaveName"
class="w-full p-2"
>
<option
v-for="option in options"
:key="option"
:value="option"
>
{{ option }}
</option>
</select>
</div>
</div>
<base-checkbox
v-model="visible"
label="顯示"
class="px-4"
/>
</div>
<div class="h-[50vh] flex items-center justify-center">
<transition-special-effects
:enter="enterName"
:leave="leaveName"
>
<div
v-if="visible"
class="flex flex-col items-center gap-4"
>
<img
src="/profile.webp"
class="mb-4 h-60 w-60 overflow-hidden border-4 border-white rounded-full shadow-xl"
>
<div class="text-xl font-bold">
鱈魚 Codfish
</div>
<div>
困擾買不到 IP69K 等級的防水電腦 ( ´•̥̥̥ ω •̥̥̥` )
</div>
</div>
</transition-special-effects>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import BaseCheckbox from '../../base-checkbox.vue'
import TransitionSpecialEffects from '../transition-special-effects.vue'
import { TransitionName } from '../type'
const visible = ref(true)
const enterName = ref<`${TransitionName}`>('wave')
const leaveName = ref<`${TransitionName}`>('wave')
const options = Object.values(TransitionName)
</script>
原理
這類特殊效果已經完全超出 CSS 範疇。
一開始往 HTML to Canvas 方向研究,但是 HTML 轉換成 Canvas 會有很多誤差,成果實在不忍直視。(́⊙◞౪◟⊙‵)
最後發現 SVG Filter 最適合,因為 SVG Filter 可以直接對 HTML 元素套用濾鏡效果。
剛好趁這個機會好好研究 SVG Filter,相當複雜,但是真的很有趣。(*´∀`)~♥
實作概念為:
- 將 SVG Filter 內容獨立為 Vue 元件,使用
v-bind
綁定參數,配合animejs
產生動畫。 - 產生唯一 ID,綁定至目標元素
style
,產生濾鏡效果。
原始碼
API
Props
interface Props {
appear?: boolean;
enter?: EnterParams;
leave?: LeaveParams;
}
Emits
const emit = defineEmits<{
(e: 'init'): void;
(e: 'beforeEnter'): void;
(e: 'afterEnter'): void;
(e: 'beforeLeave'): void;
(e: 'afterLeave'): void;
}>()
Slots
defineSlots<{
default?: () => unknown;
}>()