Special Effects Transition transition
Cool effects and bold style Transition component! ◝( •ω• )◟
Attention!
This component uses the style filter property. Make sure you are not already using filter, otherwise the original filter effects will be lost. ლ(╹◡╹ლ)
Usage Examples
Basic Usage
Usage is the same as Vue's built-in Transition component.
(Click to start the transition)
View example source code
<template>
<div class="w-full flex flex-col gap-4 border border-gray-200 rounded-xl 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 and Leave
You can specify different effects for enter and leave separately.

View example source code
<template>
<div class="w-full flex flex-col gap-4 border border-gray-200 rounded-xl 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">
{{ t('進入特效') }}
</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">
{{ t('離開特效') }}
</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="t('顯示')"
class="px-4"
/>
</div>
<div
class="h-[50vh] flex cursor-pointer items-center justify-center"
@click="visible = !visible"
>
<transition-special-effects
:enter="enterName"
:leave="leaveName"
>
<div
v-if="visible"
class="flex flex-col items-center gap-4"
>
<img
src="/low/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">
{{ t('鱈魚 Codfish') }}
</div>
<div>
{{ t('困擾買不到 IP69K 等級的防水電腦') }}
</div>
</div>
</transition-special-effects>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { useI18n } from 'vue-i18n'
import BaseCheckbox from '../../base-checkbox.vue'
import TransitionSpecialEffects from '../transition-special-effects.vue'
import { TransitionName } from '../type'
const { t } = useI18n()
const visible = ref(true)
const enterName = ref<`${TransitionName}`>('wave')
const leaveName = ref<`${TransitionName}`>('wave')
const options = Object.values(TransitionName)
</script>How It Works
These special effects go completely beyond the scope of CSS.
At first, I explored the HTML to Canvas approach, but converting HTML to Canvas produced too many inaccuracies, and the results were unbearable to look at. (́⊙◞౪◟⊙‵)
In the end, I found SVG Filter to be the best fit, because SVG Filters can directly apply filter effects to HTML elements.
This was a great opportunity to dive deep into SVG Filters -- quite complex, but truly fascinating. (*´∀`)~♥
The implementation concept is:
- SVG Filter content is separated into Vue components, with
v-bindfor parameter binding andanimejsfor animation. - A unique ID is generated and bound to the target element's
styleto produce filter effects.
Source Code
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;
}>()