modal animation
This commit is contained in:
parent
1894e37605
commit
3f96155321
2 changed files with 85 additions and 7 deletions
|
|
@ -1,18 +1,28 @@
|
|||
<template>
|
||||
<div class="mosaic-modal theme-dark layout-grid-inner" @click="onClose">
|
||||
<div class="meta">
|
||||
<div v-if="item.dl?.length" class="window dl" @click.stop>
|
||||
<div
|
||||
v-if="item.dl?.length"
|
||||
class="window dl"
|
||||
@click.stop
|
||||
ref="dlWindow"
|
||||
>
|
||||
<dl-row v-for="row in item.dl" :row="row" />
|
||||
</div>
|
||||
|
||||
<div class="window gif" @click.stop>
|
||||
<div class="window gif" @click.stop ref="gifWindow">
|
||||
<strapi-media :image="item.image" fit="contain" />
|
||||
|
||||
<strapi-link class="h6" v-bind="item.image_attribution" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="window content" @click.stop data-lenis-prevent>
|
||||
<div
|
||||
class="window content"
|
||||
@click.stop
|
||||
data-lenis-prevent
|
||||
ref="contentWindow"
|
||||
>
|
||||
<lenis instance="mosaic-modal">
|
||||
<button class="close mobile-only" @click="onClose">
|
||||
Close X
|
||||
|
|
@ -24,19 +34,80 @@
|
|||
</lenis>
|
||||
</div>
|
||||
|
||||
<button class="window close desktop-only" @click="onClose">
|
||||
<button
|
||||
class="window close desktop-only"
|
||||
@click="onClose"
|
||||
ref="closeWindow"
|
||||
>
|
||||
Close X
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import gsap from 'gsap'
|
||||
import { onMounted, ref, shallowRef } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const props = defineProps({ item: Object })
|
||||
|
||||
const router = useRouter()
|
||||
const onClose = () => router.push('/')
|
||||
const onClose = async () => {
|
||||
await animateOut()
|
||||
router.push('/')
|
||||
}
|
||||
|
||||
const dlWindow = ref()
|
||||
const gifWindow = ref()
|
||||
const contentWindow = ref()
|
||||
const closeWindow = ref()
|
||||
|
||||
// Animation
|
||||
const tl = shallowRef()
|
||||
const ANIMATION_SETTINGS = {
|
||||
duration: 0.5,
|
||||
ease: 'power3.out',
|
||||
}
|
||||
onMounted(() => {
|
||||
tl.value = gsap.timeline()
|
||||
|
||||
tl.value.fromTo(
|
||||
dlWindow.value,
|
||||
{ opacity: 0, height: 0 },
|
||||
{ opacity: 1, height: 'auto', ...ANIMATION_SETTINGS },
|
||||
)
|
||||
tl.value.fromTo(
|
||||
gifWindow.value,
|
||||
{ opacity: 0, height: 0 },
|
||||
{ opacity: 1, height: 'auto', ...ANIMATION_SETTINGS },
|
||||
'+0.1',
|
||||
)
|
||||
tl.value.fromTo(
|
||||
contentWindow.value,
|
||||
{ opacity: 0, height: 0 },
|
||||
{ opacity: 1, height: 'auto', ...ANIMATION_SETTINGS },
|
||||
'+0.1',
|
||||
)
|
||||
tl.value.fromTo(
|
||||
closeWindow.value,
|
||||
{ opacity: 0, height: 0 },
|
||||
{ opacity: 1, height: 'auto', ...ANIMATION_SETTINGS },
|
||||
'+0.1',
|
||||
)
|
||||
|
||||
tl.value.pause(0)
|
||||
})
|
||||
const animateIn = () => {
|
||||
tl.value?.play()
|
||||
}
|
||||
const animateOut = () => {
|
||||
return new Promise((resolve) => {
|
||||
if (!tl.value) return resolve()
|
||||
tl.value.eventCallback('onReverseComplete', resolve)
|
||||
tl.value.reverse()
|
||||
})
|
||||
}
|
||||
defineExpose({ animateIn, animateOut })
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
|
@ -56,6 +127,7 @@ const onClose = () => router.push('/')
|
|||
background: var(--theme-bg);
|
||||
color: var(--theme-fg);
|
||||
border-radius: desktop-vw(10px);
|
||||
overflow: hidden;
|
||||
|
||||
&.dl {
|
||||
padding: desktop-vw(12px) desktop-vw(10px);
|
||||
|
|
|
|||
|
|
@ -1,19 +1,25 @@
|
|||
<template>
|
||||
<main class="mosaic-item">
|
||||
<mosaic-modal :item="activeItem" />
|
||||
<mosaic-modal :item="activeItem" ref="modal" />
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useStrapiGlobal } from '@/composables/useStrapi'
|
||||
import { computed } from 'vue'
|
||||
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const id = route.params.id
|
||||
|
||||
const modal = ref(null)
|
||||
|
||||
const { data: global } = await useStrapiGlobal()
|
||||
|
||||
onMounted(() => {
|
||||
modal.value?.animateIn()
|
||||
})
|
||||
|
||||
const mosaicItems = computed(() => global.value?.mosaic_items || [])
|
||||
const activeItem = computed(() =>
|
||||
mosaicItems.value.find((item) => item.slug === id),
|
||||
|
|
|
|||
Loading…
Reference in a new issue