@vue-gsap-flip/core
The core package is the foundation of Vue Flip. It provides the essential functionality for creating flip animations in Vue 3 applications.
What's Included
The core package contains:
- useFlip() - The main composable that manages flip animations
- FlipElement - Vue component for easy integration
- Plugin System - Extensible architecture for custom functionality
- Type Definitions - Full TypeScript support
How It Works
Vue Flip works by leveraging GSAP's Flip plugin under the hood. Here's the basic flow:
- State Capture: Before any changes, Vue Flip captures the current state (position, size, etc.) of elements
- DOM Changes: Your Vue app makes changes to the DOM (reordering, showing/hiding, etc.)
- Animation: Vue Flip animates the elements from their old positions to their new positions
- Cleanup: The animation completes and cleanup occurs
Core Concepts
Flip Manager
The flip manager is the central orchestrator that:
- Tracks elements that need to flip
- Manages the animation lifecycle
- Handles plugin integration
- Provides configuration options
FlipElement Component
A Vue component that:
- Wraps your content
- Provides the
setEl
function for element reference - Handles the flip animation automatically
- Supports configuration options
Plugin System
An extensible system that allows you to:
- Add custom middleware
- Modify animation behavior
- Integrate with external libraries
- Create reusable functionality
Basic Usage
Demo code
vue
<script setup>
import { FlipElement } from '@vue-gsap-flip/core'
import { ref } from 'vue'
const isExpanded = ref(false)
function toggleCard () {
isExpanded.value = !isExpanded.value
}
</script>
<template>
<div class="example">
<button class="btn mb-2" @click="toggleCard">Toggle Card</button>
<FlipElement
id="card"
:config="{
flipVars: { duration: 0.3 },
flipStateVars: { props: 'borderRadius,backgroundColor' }
}"
:trigger="isExpanded"
v-slot="{ setEl }"
>
<div
:ref="setEl"
:class="{ 'card': !isExpanded, 'card--expanded': isExpanded }"
/>
</FlipElement>
</div>
</template>
<style scoped>
.example {
width: 100%;
}
.card {
background-color: white;
border-radius: 8px;
width: 100px;
height: 100px;
}
.card--expanded {
border-radius: 200px;
margin-left: 50%;
height: 200px;
width: 50%;
background-color: red;
}
</style>
Advanced Usage
For more control, you can use the useFlip
composable directly:
vue
<script setup>
import { useFlip } from '@vue-gsap-flip/core'
const flipManager = useFlip()
// Trigger a flip animation
async function triggerFlip () {
flipManager.detach('CUSTOM-ID', elementRef, { clone: true })
// Make DOM changes
// if you want you can animate animate the clone element
// for example during page transitions
const data = store.get('CUSTOM-ID')
await gsap.to(data.clone, { scale: 2 })
store.set('flip-img', { ...data, state: Flip.getState(data.clone as HTMLElement) })
// flip to the current position
flipManager.attach('CUSTOM-ID', elementRef)
}
</script>
A real example can be during a vue transition (or a page transition), where we can move the clone during the transition.
Step 1
Demo code
vue
<script setup lang="ts">
import { FlipElement, useFlip } from '@vue-gsap-flip/core'
import { gsap } from 'gsap'
import { Flip } from 'gsap/Flip'
import { ref } from 'vue'
const manager = useFlip()
const toggle = ref(false)
const transitioning = ref(false)
const config = { clone: true, flipStateVars: { scale: true } }
function onLeave (el: Element, done: () => void) {
const tl = gsap.timeline({ onComplete: () => done() })
tl.to(gsap.utils.toArray('.box-text', el), { autoAlpha: 0, duration: 0.5 })
const data = manager.store.get('box')
if (data?.clone) {
tl.to(data.clone, {
rotate: 360,
x: window.innerWidth / 2,
xPercent: -50,
yPercent: -150,
duration: 0.5,
onComplete: () => {
manager.store.set('box', { ...data, state: Flip.getState(data.clone as HTMLElement, data.config.flipStateVars) })
}
})
}
}
function onEnter (el: Element, done: () => void) {
const tl = gsap.timeline({ onComplete: () => done() })
tl.from(gsap.utils.toArray('.box-text', el), { autoAlpha: 0, duration: 0.5 })
}
</script>
<template>
<div class="w-full">
<button class="btn mb-2" :disabled="transitioning" @click="toggle = !toggle">Toggle</button>
<div class="border-solid border-blue">
<Transition
mode="out-in"
:css="false"
@after-enter="transitioning = false"
@before-leave="transitioning = true"
@enter="onEnter"
@leave="onLeave"
>
<div v-if="!toggle" class="grid grid-cols-2">
<div class="box box-text">
<p>Step 1</p>
</div>
<div class="box">
<FlipElement id="box" :config="config" v-slot="{ setEl }">
<div :ref="setEl" class="w-4 h-4 bg-blue" />
</FlipElement>
</div>
</div>
<div v-else class="grid grid-cols-2">
<div class="box">
<FlipElement id="box" :config="config" v-slot="{ setEl }">
<div :ref="setEl" class="w-30 h-30 bg-blue" />
</FlipElement>
</div>
<div class="box box-text">
<p>Step 2</p>
</div>
</div>
</Transition>
</div>
</div>
</template>
<style scoped>
.box {
@apply h-40 p-4 flex items-center justify-center;
}
</style>
Navigation
- Flip Manager - Learn about the core flip manager
- FlipElement Component - Understand the Vue component
- Plugin System - Learn about the extensible plugin architecture
Next Steps
Ready to dive deeper? Start with the Flip Manager to understand the core concepts.