style: 页面动画效果
This commit is contained in:
234
src/views/AwardPage/components/PrizesSection.vue
Normal file
234
src/views/AwardPage/components/PrizesSection.vue
Normal file
@@ -0,0 +1,234 @@
|
||||
<template>
|
||||
<div
|
||||
class="prizes-container container flex align-center space-between"
|
||||
ref="prizesRef"
|
||||
>
|
||||
<div class="left flex flex-col flex-center">
|
||||
<div
|
||||
class="title"
|
||||
ref="prizesTitleRef"
|
||||
>
|
||||
Award & Prizes
|
||||
</div>
|
||||
<!-- <img src="@/assets/images/award/bloom_logo.png" class="logo" /> -->
|
||||
<div
|
||||
class="desc"
|
||||
ref="prizesSubTitleRef"
|
||||
>
|
||||
Recongnition
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="right"
|
||||
ref="prizesRightRef"
|
||||
>
|
||||
<div
|
||||
class="prize-item flex flex-col flex-center"
|
||||
v-for="item in prizes"
|
||||
:key="item.name"
|
||||
>
|
||||
<div class="prize-money">{{ item.money }}</div>
|
||||
<div class="prize-name">{{ item.name }}</div>
|
||||
<div class="prize-desc flex flex-col flex-center">
|
||||
<div
|
||||
class="desc-item"
|
||||
v-for="el in item.desc"
|
||||
>
|
||||
{{ el }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import { gsap } from 'gsap'
|
||||
|
||||
const prizes = [
|
||||
{
|
||||
money: 'US$5000',
|
||||
name: 'Grand Prize',
|
||||
desc: ['Cash Award', 'Award Ceritificate', 'Global Media Exposure']
|
||||
},
|
||||
{
|
||||
money: 'US$3000',
|
||||
name: 'First Runner-Up',
|
||||
desc: ['Cash Award', 'Award Ceritificate', 'Global Media Exposure']
|
||||
},
|
||||
{
|
||||
money: 'US$2000',
|
||||
name: 'Second Runner-Up',
|
||||
desc: ['Cash Award', 'Award Ceritificate', 'Global Media Exposure']
|
||||
},
|
||||
{
|
||||
money: 'Certification',
|
||||
name: 'Finalists',
|
||||
desc: ['Award Ceritificate', 'Global Media Exposure']
|
||||
}
|
||||
]
|
||||
|
||||
const prizesRef = ref<HTMLElement | null>(null)
|
||||
const prizesTitleRef = ref<HTMLElement | null>(null)
|
||||
const prizesSubTitleRef = ref<HTMLElement | null>(null)
|
||||
const prizesRightRef = ref<HTMLElement | null>(null)
|
||||
const hasPlayedPrizesAnim = ref(false)
|
||||
let prizesObserver: IntersectionObserver | null = null
|
||||
|
||||
const setupPrizesInitialState = () => {
|
||||
const titleEls = [prizesTitleRef.value, prizesSubTitleRef.value].filter(
|
||||
Boolean
|
||||
) as HTMLElement[]
|
||||
if (titleEls.length) {
|
||||
gsap.set(titleEls, {
|
||||
opacity: 0,
|
||||
scale: 0,
|
||||
transformOrigin: '50% 50%'
|
||||
})
|
||||
}
|
||||
if (prizesRightRef.value) {
|
||||
gsap.set(prizesRightRef.value, {
|
||||
opacity: 0,
|
||||
y: 40,
|
||||
scale: 1.08
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const playPrizesAnimation = () => {
|
||||
if (hasPlayedPrizesAnim.value) return
|
||||
const titleEls = [prizesTitleRef.value, prizesSubTitleRef.value].filter(
|
||||
Boolean
|
||||
) as HTMLElement[]
|
||||
|
||||
const tl = gsap.timeline({ defaults: { ease: 'power2.out' } })
|
||||
if (titleEls.length) {
|
||||
tl.to(titleEls, {
|
||||
opacity: 1,
|
||||
scale: 1,
|
||||
duration: 0.6,
|
||||
ease: 'back.out(1.6)',
|
||||
stagger: 0.1
|
||||
})
|
||||
}
|
||||
if (prizesRightRef.value) {
|
||||
tl.to(
|
||||
prizesRightRef.value,
|
||||
{
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
scale: 1,
|
||||
duration: 0.55,
|
||||
ease: 'back.out(1.4)'
|
||||
},
|
||||
titleEls.length ? '-=0.15' : 0
|
||||
)
|
||||
}
|
||||
|
||||
hasPlayedPrizesAnim.value = true
|
||||
prizesObserver?.disconnect()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
setupPrizesInitialState()
|
||||
if ('IntersectionObserver' in window) {
|
||||
prizesObserver = new IntersectionObserver(
|
||||
entries => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
playPrizesAnimation()
|
||||
}
|
||||
})
|
||||
},
|
||||
{ threshold: 0.25 }
|
||||
)
|
||||
if (prizesRef.value) prizesObserver.observe(prizesRef.value)
|
||||
} else {
|
||||
playPrizesAnimation()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
prizesObserver?.disconnect()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.prizes-container {
|
||||
background: url('@/assets/images/award/prizes_bg.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
padding: 0 21.4rem 0 34.2rem;
|
||||
box-sizing: border-box;
|
||||
.left {
|
||||
row-gap: 3.6rem;
|
||||
.title {
|
||||
text-align: center;
|
||||
font-family: 'PoppinsBold';
|
||||
font-weight: 600;
|
||||
font-size: 4rem;
|
||||
color: #fff;
|
||||
}
|
||||
.desc {
|
||||
text-align: center;
|
||||
color: #f95750;
|
||||
font-family: 'Poppins';
|
||||
font-weight: 400;
|
||||
font-size: 3rem;
|
||||
}
|
||||
}
|
||||
.right {
|
||||
// height: 45.4rem;
|
||||
// padding: 4.6rem 6.1rem 4.6rem 0;
|
||||
box-sizing: border-box;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-template-rows: repeat(2, 1fr);
|
||||
row-gap: 4.2rem;
|
||||
column-gap: 4.4rem;
|
||||
// flex: 1;
|
||||
.prize-item {
|
||||
width: 35.5rem;
|
||||
height: 32.8rem;
|
||||
color: #fff;
|
||||
padding: 4.5rem 0 4.8rem 0;
|
||||
justify-content: space-between;
|
||||
background: url('@/assets/images/award/first_bg.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
&:nth-of-type(2) {
|
||||
background: url('@/assets/images/award/second_bg.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
&:nth-of-type(3) {
|
||||
background: url('@/assets/images/award/grand_bg.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
&:nth-of-type(4) {
|
||||
background: url('@/assets/images/award/certification_bg.png')
|
||||
no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
.prize-money {
|
||||
font-family: 'PoppinsBold';
|
||||
font-weight: bold;
|
||||
font-size: 4rem;
|
||||
}
|
||||
.prize-name {
|
||||
font-family: 'PoppinsMedium';
|
||||
font-weight: 500;
|
||||
font-size: 2.8rem;
|
||||
}
|
||||
.prize-desc {
|
||||
color: #e0e0e0;
|
||||
font-family: 'Arial';
|
||||
font-weight: 400;
|
||||
font-size: 2rem;
|
||||
line-height: 3rem;
|
||||
height: 8.9rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user