feat(ui-transitions): more transitions

Signed-off-by: Neko Ayaka <neko@ayaka.moe>
This commit is contained in:
Neko Ayaka
2025-03-06 13:52:12 +08:00
parent 14c2960cb2
commit 6e35621eb7
7 changed files with 228 additions and 0 deletions
@@ -30,5 +30,17 @@ const route = useRoute()
>
4
</RouterLink>
<RouterLink
rounded-lg px-7 py-3 transition="all duration-250 ease-in-out" to="/transition-5"
:class="[route.path === '/transition-5' ? 'bg-neutral-200 dark:bg-neutral-500' : 'bg-neutral-100 dark:bg-neutral-700']"
>
5
</RouterLink>
<RouterLink
rounded-lg px-7 py-3 transition="all duration-250 ease-in-out" to="/transition-6"
:class="[route.path === '/transition-6' ? 'bg-neutral-200 dark:bg-neutral-500' : 'bg-neutral-100 dark:bg-neutral-700']"
>
6
</RouterLink>
</div>
</template>
@@ -0,0 +1,15 @@
<script setup lang="ts">
import { definePage } from 'unplugin-vue-router/runtime'
import Buttons from '../components/Buttons.vue'
definePage({
meta: {
stageTransition: 'fantasy-fall',
},
})
</script>
<template>
<Buttons />
</template>
@@ -0,0 +1,15 @@
<script setup lang="ts">
import { definePage } from 'unplugin-vue-router/runtime'
import Buttons from '../components/Buttons.vue'
definePage({
meta: {
stageTransition: 'rectangles-rotate',
},
})
</script>
<template>
<Buttons />
</template>
@@ -0,0 +1,65 @@
<script setup lang="ts">
import { onMounted } from 'vue'
const props = withDefaults(defineProps<{
primaryColor?: string
duration?: number
delay?: number
borderRadius?: number
}>(), {
primaryColor: '#eee',
duration: 0.6,
delay: 0,
borderRadius: 50,
})
onMounted(() => {
document.documentElement.style.setProperty('--fantasy-fall-color', props.primaryColor)
document.documentElement.style.setProperty('--fantasy-fall-duration', `${props.duration}s`)
document.documentElement.style.setProperty('--fantasy-fall-delay', `${props.delay}s`)
document.documentElement.style.setProperty('--fantasy-fall-radius', `${props.borderRadius}%`)
})
</script>
<template>
<div class="fantasy-fall-transition" />
</template>
<style scoped>
.fantasy-fall-transition {
position: absolute;
inset: 0;
overflow: hidden;
&::before {
content: '';
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: var(--fantasy-fall-color);
transform: translateY(-100%);
border-bottom-left-radius: var(--fantasy-fall-radius);
border-bottom-right-radius: var(--fantasy-fall-radius);
animation: fantasy-fall var(--fantasy-fall-duration) ease-out var(--fantasy-fall-delay) forwards;
}
}
@keyframes fantasy-fall {
0% {
transform: translateY(-100%);
}
50% {
transform: translateY(0%);
}
100% {
transform: translateY(0%);
border-bottom-right-radius: 0%;
border-bottom-left-radius: 0%;
}
}
</style>
@@ -0,0 +1,108 @@
<script setup lang="ts">
import { onMounted } from 'vue'
const props = withDefaults(defineProps<{
primaryColor?: string
secondaryColor?: string
tertiaryColor?: string
duration?: number
delay?: number
rotation?: number
staggerDelay?: number
}>(), {
primaryColor: '#ebcb8b', // First circle (top-left)
secondaryColor: '#c56370', // Second circle (bottom-right)
tertiaryColor: '#43445b', // Third circle (center)
duration: 0.6,
delay: 0,
rotation: 270,
staggerDelay: 0.1, // Delay between each circle animation
})
onMounted(() => {
// Set CSS variables for all three circles
document.documentElement.style.setProperty('--rectangle-rotate-1-color', props.primaryColor)
document.documentElement.style.setProperty('--rectangle-rotate-2-color', props.secondaryColor)
document.documentElement.style.setProperty('--rectangle-rotate-3-color', props.tertiaryColor)
document.documentElement.style.setProperty('--rectangle-rotate-duration', `${props.duration}s`)
document.documentElement.style.setProperty('--rectangle-rotate-delay', `${props.delay}s`)
document.documentElement.style.setProperty('--rectangle-rotate-stagger', `${props.staggerDelay}s`)
document.documentElement.style.setProperty('--rectangle-rotate-rotation', `${props.rotation}deg`)
})
</script>
<template>
<div class="rectangle-rotate-transition">
<!-- First rectangle (top-left) -->
<div class="rectangle rectangle-rotate-1">
<div />
</div>
<!-- Second rectangle (bottom-right) -->
<div class="rectangle rectangle-rotate-2">
<div />
</div>
<!-- Third rectangle (center) -->
<div class="rectangle rectangle-rotate-3">
<div />
</div>
</div>
</template>
<style scoped>
.rectangle-rotate-transition {
position: absolute;
inset: 0;
overflow: hidden;
}
.rectangle {
position: absolute;
width: 100%;
height: 100%;
}
.rectangle div {
position: absolute;
width: 100vmax;
height: 100vmax;
transform: scale(0);
}
/* 1 - Top Left */
.rectangle-rotate-1 div {
top: -50vmax;
left: -50vmax;
background-color: var(--rectangle-rotate-1-color);
animation: expand-rotate var(--rectangle-rotate-duration) ease calc(var(--rectangle-rotate-delay) + 0s) forwards;
}
/* 2 - Bottom Right */
.rectangle-rotate-2 div {
bottom: -50vmax;
right: -50vmax;
background-color: var(--rectangle-rotate-2-color);
animation: expand-rotate var(--rectangle-rotate-duration) ease
calc(var(--rectangle-rotate-delay) + var(--rectangle-rotate-stagger)) forwards;
}
/* 3 - Center */
.rectangle-rotate-3 div {
top: calc(50% - 50vmax);
left: calc(50% - 50vmax);
background-color: var(--rectangle-rotate-3-color);
animation: expand-rotate var(--rectangle-rotate-duration) ease
calc(var(--rectangle-rotate-delay) + calc(var(--rectangle-rotate-stagger) * 2)) forwards;
}
@keyframes expand-rotate {
from {
transform: scale(0) rotate(0deg);
}
to {
transform: scale(1) rotate(var(--rectangle-rotate-rotation));
}
}
</style>
@@ -3,7 +3,9 @@ import { ref, shallowRef } from 'vue'
import { useRouter } from 'vue-router'
import ArrowTransition from './ArrowTransition.vue'
import FantasyFallTransition from './FantasyFallTransition.vue'
import MultipleBlocksRevealTransition from './MultipleBlocksRevealTransition.vue'
import RectanglesRotateTransition from './RectanglesRotateTransition.vue'
import SlideTransition from './SlideTransition.vue'
import SlopeSlideTransition from './SlopeSlideTransition.vue'
@@ -20,6 +22,8 @@ type TransitionComponent =
| typeof SlopeSlideTransition
| typeof ArrowTransition
| typeof MultipleBlocksRevealTransition
| typeof FantasyFallTransition
| typeof RectanglesRotateTransition
const router = useRouter()
const showTransition = ref(false)
@@ -45,6 +49,14 @@ const transitions = shallowRef<Record<string, {
component: MultipleBlocksRevealTransition,
duration: 2800,
},
'fantasy-fall': {
component: FantasyFallTransition,
duration: 2700,
},
'rectangles-rotate': {
component: RectanglesRotateTransition,
duration: 2700,
},
})
function triggerTransition(name: string) {
@@ -1,4 +1,5 @@
export { default as ArrowTransition } from './ArrowTransition.vue'
export { default as FantasyFallTransition } from './FantasyFallTransition.vue'
export { default as MultipleBlocksRevealTransition } from './MultipleBlocksRevealTransition.vue'
export { default as SlideTransition } from './SlideTransition.vue'
export { default as SlopeSlideTransition } from './SlopeSlideTransition.vue'