Files
aida_front/src/views/AwardPage/components/Bloom.vue

201 lines
4.1 KiB
Vue
Raw Normal View History

2026-01-20 16:41:37 +08:00
<template>
2026-01-30 17:21:11 +08:00
<div class="bloom flex flex-col align-center">
2026-01-20 16:41:37 +08:00
<div
class="title"
ref="titleRef"
>
Bloom Your Creativity
</div>
<div
class="season"
ref="subtitleRef"
>
Theme of 2026
</div>
<div
class="desc"
ref="textRef"
>
2026-01-30 17:21:11 +08:00
<p class="section-1">
The
<span class="arial-bold">AiDA Global Design Award 2026</span>
is an
<span class="arial-bold">international design competition</span>
hosted by
<span class="arial-bold">CodeCreate</span>
, a globally leading
<br />
<span class="arial-bold">AI fashion solutions provider,</span>
celebrating the future of creativity powered by artificial intelligence.
<br />
Bringing together designers from around the world, AiDA empowers AI as a
creative partnerpushing fashion beyond
<br />
traditional boundaries and unlocking new possibilities where technology
amplifies human imagination.
</p>
<p class="section-2">
Under the theme
<span class="arial-bold">
Where Imagination Meets Innovation, Creativity Blooms,
</span>
participants are invited to transform bold ideas
<br />
into extraordinary designs, seamlessly merging human artistry with
artificial intelligence to shape the next era of fashion.
</p>
2026-01-20 16:41:37 +08:00
</div>
</div>
</template>
<script setup lang="ts">
2026-01-26 12:27:55 +08:00
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { gsap } from 'gsap'
2026-01-20 16:41:37 +08:00
2026-01-26 12:27:55 +08:00
const titleRef = ref<HTMLElement | null>(null)
const subtitleRef = ref<HTMLElement | null>(null)
const textRef = ref<HTMLElement | null>(null)
2026-01-20 16:41:37 +08:00
2026-01-26 12:27:55 +08:00
const hasPlayedBloomAnim = ref(false)
let bloomObserver: IntersectionObserver | null = null
const setupBloomInitialState = () => {
2026-01-30 17:21:11 +08:00
const titleEls = [titleRef.value, subtitleRef.value].filter(
Boolean
) as HTMLElement[]
2026-01-26 12:27:55 +08:00
if (titleEls.length) {
gsap.set(titleEls, {
opacity: 0,
// start larger than final size, then animate down to scale:1
scale: 1.6,
transformOrigin: '50% 50%'
})
}
if (textRef.value) {
// start below and hidden
gsap.set(textRef.value, {
opacity: 0,
y: 60
})
}
}
const playBloomAnimation = () => {
if (hasPlayedBloomAnim.value) return
2026-01-30 17:21:11 +08:00
const titleEls = [titleRef.value, subtitleRef.value].filter(
Boolean
) as HTMLElement[]
2026-01-26 12:27:55 +08:00
const textEl = textRef.value
if (!titleEls.length || !textEl) return
const tl = gsap.timeline({ defaults: { ease: 'power2.out' } })
tl.to(titleEls, {
opacity: 1,
scale: 1,
duration: 0.9,
ease: 'back.out(1.6)',
stagger: 0.12
})
tl.to(
textEl,
{
opacity: 1,
y: -12,
scale: 1.05,
duration: 0.3,
ease: 'power2.out'
},
2026-01-30 17:21:11 +08:00
'-=0.3'
2026-01-26 12:27:55 +08:00
)
tl.to(
textEl,
{
y: 0,
scale: 1,
duration: 0.18,
ease: 'bounce.out'
},
'+=0.08'
)
hasPlayedBloomAnim.value = true
bloomObserver?.disconnect()
}
onMounted(() => {
nextTick(() => {
setupBloomInitialState()
if ('IntersectionObserver' in window) {
bloomObserver = new IntersectionObserver(
2026-01-30 17:21:11 +08:00
entries => {
entries.forEach(entry => {
2026-01-26 12:27:55 +08:00
if (entry.isIntersecting) {
playBloomAnimation()
}
})
},
{ threshold: 0.3 }
)
if (titleRef.value) {
bloomObserver.observe(titleRef.value)
}
} else {
// fallback
playBloomAnimation()
}
})
})
onBeforeUnmount(() => {
bloomObserver?.disconnect()
})
2026-01-20 16:41:37 +08:00
</script>
<style scoped lang="less">
2026-01-30 17:21:11 +08:00
p {
margin: 0;
padding: 0;
}
.arial-bold {
font-family: 'ArialBold';
font-weight: 700;
}
2026-01-20 16:41:37 +08:00
.bloom {
2026-01-30 17:21:11 +08:00
height: 108rem;
2026-01-20 16:41:37 +08:00
padding-top: 12.8rem;
font-family: 'Poppins';
background: url('@/assets/images/award/bloom_bg.png') no-repeat;
background-size: 100% 100%;
.title {
font-size: 4rem;
color: #232323;
margin-bottom: 2.4rem;
}
.logo {
margin-bottom: 2.2rem;
}
.season {
font-size: 3rem;
color: #c7342c;
margin-bottom: 6.6rem;
}
.desc {
font-family: 'Arial';
2026-01-30 17:21:11 +08:00
font-weight: 400;
font-size: 2.4rem;
2026-01-20 16:41:37 +08:00
color: #585858;
text-align: center;
padding: 0 21.5rem;
line-height: 4.5rem;
margin-bottom: 12.3rem;
2026-01-30 17:21:11 +08:00
.section-2{
margin-top: 4rem;
}
2026-01-20 16:41:37 +08:00
}
}
</style>