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>
|
<template>
|
||||||
<div class="mosaic-modal theme-dark layout-grid-inner" @click="onClose">
|
<div class="mosaic-modal theme-dark layout-grid-inner" @click="onClose">
|
||||||
<div class="meta">
|
<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" />
|
<dl-row v-for="row in item.dl" :row="row" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="window gif" @click.stop>
|
<div class="window gif" @click.stop ref="gifWindow">
|
||||||
<strapi-media :image="item.image" fit="contain" />
|
<strapi-media :image="item.image" fit="contain" />
|
||||||
|
|
||||||
<strapi-link class="h6" v-bind="item.image_attribution" />
|
<strapi-link class="h6" v-bind="item.image_attribution" />
|
||||||
</div>
|
</div>
|
||||||
</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">
|
<lenis instance="mosaic-modal">
|
||||||
<button class="close mobile-only" @click="onClose">
|
<button class="close mobile-only" @click="onClose">
|
||||||
Close X
|
Close X
|
||||||
|
|
@ -24,19 +34,80 @@
|
||||||
</lenis>
|
</lenis>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="window close desktop-only" @click="onClose">
|
<button
|
||||||
|
class="window close desktop-only"
|
||||||
|
@click="onClose"
|
||||||
|
ref="closeWindow"
|
||||||
|
>
|
||||||
Close X
|
Close X
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import gsap from 'gsap'
|
||||||
|
import { onMounted, ref, shallowRef } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
const props = defineProps({ item: Object })
|
const props = defineProps({ item: Object })
|
||||||
|
|
||||||
const router = useRouter()
|
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>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|
@ -56,6 +127,7 @@ const onClose = () => router.push('/')
|
||||||
background: var(--theme-bg);
|
background: var(--theme-bg);
|
||||||
color: var(--theme-fg);
|
color: var(--theme-fg);
|
||||||
border-radius: desktop-vw(10px);
|
border-radius: desktop-vw(10px);
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
&.dl {
|
&.dl {
|
||||||
padding: desktop-vw(12px) desktop-vw(10px);
|
padding: desktop-vw(12px) desktop-vw(10px);
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,25 @@
|
||||||
<template>
|
<template>
|
||||||
<main class="mosaic-item">
|
<main class="mosaic-item">
|
||||||
<mosaic-modal :item="activeItem" />
|
<mosaic-modal :item="activeItem" ref="modal" />
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useStrapiGlobal } from '@/composables/useStrapi'
|
import { useStrapiGlobal } from '@/composables/useStrapi'
|
||||||
import { computed } from 'vue'
|
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const id = route.params.id
|
const id = route.params.id
|
||||||
|
|
||||||
|
const modal = ref(null)
|
||||||
|
|
||||||
const { data: global } = await useStrapiGlobal()
|
const { data: global } = await useStrapiGlobal()
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
modal.value?.animateIn()
|
||||||
|
})
|
||||||
|
|
||||||
const mosaicItems = computed(() => global.value?.mosaic_items || [])
|
const mosaicItems = computed(() => global.value?.mosaic_items || [])
|
||||||
const activeItem = computed(() =>
|
const activeItem = computed(() =>
|
||||||
mosaicItems.value.find((item) => item.slug === id),
|
mosaicItems.value.find((item) => item.slug === id),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue