Motion Gallery util
A gallery where layouts transform freely and dynamically. Groovy!
Examples
Basic Usage
Watch the image layout dynamically change when you switch the type
. Magic!
loading...
Check out the example source code
vue
<template>
<div class="mt-4 w-full flex flex-col gap-4">
<util-motion-gallery
v-slot="{ isLoading }"
class="h-full"
:image-list
:layout
>
<transition name="opacity">
<div
v-if="isLoading"
class="absolute h-full w-full flex-center bg-black/50"
>
<div class="flex flex-col items-center gap-4">
<div class="h-10 w-10 animate-spin border-4 border-white border-t-transparent rounded-full" />
<span class="text-2xl text-white tracking-widest">
loading...
</span>
</div>
</div>
</transition>
</util-motion-gallery>
<select-stepper
v-model="type"
:options
class="w-full text-center"
/>
</div>
</template>
<script setup lang="ts">
import type { ComponentProps } from 'vue-component-type-helpers'
import { computed, ref } from 'vue'
import SelectStepper from '../../select-stepper.vue'
import UtilMotionGallery from '../util-motion-gallery.vue'
type Props = ComponentProps<typeof UtilMotionGallery>
type LayoutType = NonNullable<Props['layout']>['type']
const imageList: [string, ...string[]] = [
'/low/painting-codfish-bakery.webp',
'/low/painting-codfish-rain.webp',
'/low/photography-fireworks.webp',
'/low/photography-morning-light-of-rice.webp',
'/low/photography-big-stupid-bird.webp',
'/low/photography-ears-of-rice.webp',
'/low/photography-gaomei-windmill.webp',
'/low/photography-spider-at-night.webp',
'/low/photography-street-cat.webp',
'/low/photography-afternoon-cicada-chirping.webp',
'/low/photography-whispers-of-the-setting-sun.webp',
'/low/photography-city-of-lights-from-the-mountainside.webp',
]
const type = ref<LayoutType>('grid')
const layout = computed(() => ({
type: type.value,
}))
const options: LayoutType[] = [
'grid',
'wheel',
'tunnel',
'ball',
]
</script>
<style scoped lang="sass">
.opacity-enter-active, .opacity-leave-active
transition-duration: 0.4s
.opacity-enter-from, .opacity-leave-to
opacity: 0 !important
</style>
How it Works
It leverages the power of babylon.js for all the 3D object transformations like rotation, scaling, and translation, spiced up with anime.js for smooth animations.
Spin Me Right Round
When rotating objects in 3D space, the order of rotation around each axis matters—a lot! It totally changes the final result.
So, rotating 90 degrees on each axis in XYZ order gives a different outcome than ZYX or YZX. Who knew, right?! ( ゚ ∀。)
For the nitty-gritty details, check out Sequencing Rotations
My head spins just thinking about it sometimes ~( ゚ ∀。)~
Source Code
API
Props
type Layout = {
type: 'grid';
gap?: number;
} | {
type: 'wheel';
radius?: number;
} | {
type: 'tunnel';
radius?: number;
depthGap?: number;
} | {
type: 'ball';
radius?: number;
}
interface Props {
layout?: Layout;
/** 不足 30 張會自動重複填充至 30 張 */
imageList: [string, ...string[]];
fpsVisible?: boolean;
/** 背景色。無限遠處的顏色 */
clearColor?: Color4;
/** 霧化色。足夠遠處的照片會被此顏色籠罩 */
fogColor?: Color3;
}