style: section移动端

This commit is contained in:
2026-03-19 13:38:30 +08:00
parent 5dd8840a0a
commit 4989bb7156
2 changed files with 173 additions and 138 deletions

View File

Before

Width:  |  Height:  |  Size: 816 KiB

After

Width:  |  Height:  |  Size: 816 KiB

View File

@@ -1,27 +1,24 @@
<template> <template>
<div <div
class="selection-container container flex flex-col align-center" class="selection-container container flex flex-col align-center"
ref="selectionRef" ref="selectionRef"
> :class="{ mobile: isMobile }"
<div class="title">{{ $t('AwardsPage.selectionCriteria') }}</div> >
<!-- <img src="@/assets/images/award/bloom_logo.png" class="logo" /> --> <div class="title">{{ $t('AwardsPage.selectionCriteria') }}</div>
<div class="sub-title">{{ $t('AwardsPage.evaluation') }}</div> <!-- <img src="@/assets/images/award/bloom_logo.png" class="logo" /> -->
<div class="criteria-list flex" ref="criteriaListRef"> <div class="sub-title">{{ $t('AwardsPage.evaluation') }}</div>
<div <div class="criteria-list flex" ref="criteriaListRef">
class="item flex flex-col align-center" <div class="item flex flex-col align-center" v-for="item in criteriaList" :key="item.name">
v-for="item in criteriaList" <img :src="item.icon" class="icon" :style="item.style" />
:key="item.name" <div class="name">{{ $t(item.name) }}</div>
> <div class="desc">{{ $t(item.desc) }}</div>
<img :src="item.icon" class="icon" :style="item.style" /> </div>
<div class="name">{{ $t(item.name) }}</div> </div>
<div class="desc">{{ $t(item.desc) }}</div> </div>
</div>
</div>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { nextTick, onBeforeUnmount, onMounted, ref } from 'vue' import { nextTick, onBeforeUnmount, onMounted, ref, inject } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { gsap } from 'gsap' import { gsap } from 'gsap'
import criteria1 from '@/assets/images/award/criteria_1.png' import criteria1 from '@/assets/images/award/criteria_1.png'
@@ -31,31 +28,32 @@ import criteria4 from '@/assets/images/award/criteria_4.png'
const { t } = useI18n() const { t } = useI18n()
const isMobile = inject('isMobile')
const criteriaList = ref([ const criteriaList = ref([
{ {
icon: criteria1, icon: criteria1,
name: 'AwardsPage.originality', name: 'AwardsPage.originality',
desc: 'AwardsPage.originalityDesc', desc: 'AwardsPage.originalityDesc',
style: { width: '13rem', height: '17rem' } style: { width: '13rem', height: '17rem' }
}, },
{ {
icon: criteria2, icon: criteria2,
name: 'AwardsPage.creativity', name: 'AwardsPage.creativity',
desc: 'AwardsPage.creativityDesc', desc: 'AwardsPage.creativityDesc',
style: { width: '16rem', height: '18rem' } style: { width: '16rem', height: '18rem' }
}, },
{ {
icon: criteria3, icon: criteria3,
name: 'AwardsPage.aidaIntegration', name: 'AwardsPage.aidaIntegration',
desc: 'AwardsPage.aidaIntegrationDesc', desc: 'AwardsPage.aidaIntegrationDesc',
style: { width: '16rem', height: '18rem' } style: { width: '16rem', height: '18rem' }
}, },
{ {
icon: criteria4, icon: criteria4,
name: 'AwardsPage.execution', name: 'AwardsPage.execution',
desc: 'AwardsPage.executionDesc', desc: 'AwardsPage.executionDesc',
style: { width: '18.8rem', height: '18rem' } style: { width: '18.8rem', height: '18rem' }
} }
]) ])
const selectionRef = ref<HTMLElement | null>(null) const selectionRef = ref<HTMLElement | null>(null)
@@ -64,115 +62,152 @@ const hasPlayedSelectionAnim = ref(false)
let selectionObserver: IntersectionObserver | null = null let selectionObserver: IntersectionObserver | null = null
const setupSelectionInitialState = () => { const setupSelectionInitialState = () => {
const items = const items = criteriaListRef.value?.querySelectorAll<HTMLElement>('.item') ?? []
criteriaListRef.value?.querySelectorAll<HTMLElement>('.item') ?? [] if (items.length) {
if (items.length) { gsap.set(items, {
gsap.set(items, { opacity: 0,
opacity: 0, scale: 0,
scale: 0, transformOrigin: '50% 50%'
transformOrigin: '50% 50%' })
}) }
}
} }
const playSelectionAnimation = () => { const playSelectionAnimation = () => {
if (hasPlayedSelectionAnim.value) return if (hasPlayedSelectionAnim.value) return
const items = const items = criteriaListRef.value?.querySelectorAll<HTMLElement>('.item') ?? []
criteriaListRef.value?.querySelectorAll<HTMLElement>('.item') ?? [] if (!items.length) return
if (!items.length) return
gsap.to(items, { gsap.to(items, {
opacity: 1, opacity: 1,
scale: 1, scale: 1,
duration: 0.6, duration: 0.6,
ease: 'back.out(1.6)', ease: 'back.out(1.6)',
stagger: 0.3 stagger: 0.3
}) })
hasPlayedSelectionAnim.value = true hasPlayedSelectionAnim.value = true
selectionObserver?.disconnect() selectionObserver?.disconnect()
} }
onMounted(() => { onMounted(() => {
nextTick(() => { nextTick(() => {
setupSelectionInitialState() setupSelectionInitialState()
if ('IntersectionObserver' in window) { if ('IntersectionObserver' in window) {
selectionObserver = new IntersectionObserver( selectionObserver = new IntersectionObserver(
(entries) => { (entries) => {
entries.forEach((entry) => { entries.forEach((entry) => {
if (entry.isIntersecting) { if (entry.isIntersecting) {
playSelectionAnimation() playSelectionAnimation()
} }
}) })
}, },
{ threshold: 0.25 } { threshold: 0.25 }
) )
if (selectionRef.value) { if (selectionRef.value) {
selectionObserver.observe(selectionRef.value) selectionObserver.observe(selectionRef.value)
} }
} else { } else {
playSelectionAnimation() playSelectionAnimation()
} }
}) })
}) })
onBeforeUnmount(() => { onBeforeUnmount(() => {
selectionObserver?.disconnect() selectionObserver?.disconnect()
}) })
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
.selection-container { .selection-container {
background: url('@/assets/images/award/selection_bg.png') no-repeat; background: url('@/assets/images/award/selection_bg.png') no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
padding-top: 9.3rem; padding-top: 9.3rem;
.title { .title {
color: #fff; color: #fff;
font-family: 'PoppinsBold'; font-family: 'PoppinsBold';
font-weight: 600; font-weight: 600;
font-size: 4rem; font-size: 4rem;
margin-bottom: 2.4rem; margin-bottom: 2.4rem;
} }
.logo { .logo {
margin: 2.3rem 0 2.3rem; margin: 2.3rem 0 2.3rem;
} }
.sub-title { .sub-title {
color: #f95750; color: #f95750;
font-family: 'Popins'; font-family: 'Popins';
font-weight: 400; font-weight: 400;
font-size: 3rem; font-size: 3rem;
margin-bottom: 11.8rem; margin-bottom: 11.8rem;
} }
.criteria-list { .criteria-list {
column-gap: 6rem; column-gap: 6rem;
.item { .item {
height: 44rem; height: 44rem;
width: 32.2rem; width: 32.2rem;
box-sizing: border-box; box-sizing: border-box;
&:nth-of-type(3) { &:nth-of-type(3) {
background: url('@/assets/images/award/criteria_bg.png') no-repeat; background: url('@/assets/images/award/criteria_bg.png') no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
} }
.icon { .icon {
width: 18.8rem; width: 18.8rem;
height: 18rem; height: 18rem;
} }
.name { .name {
font-family: 'PoppinsMedium'; font-family: 'PoppinsMedium';
font-weight: 500; font-weight: 500;
font-size: 2.8rem; font-size: 2.8rem;
color: #fff; color: #fff;
margin: 2rem 0 5rem; margin: 2rem 0 5rem;
} }
.desc { .desc {
font-family: 'Arial'; font-family: 'Arial';
font-weight: 400; font-weight: 400;
font-size: 2rem; font-size: 2rem;
color: #e0e0e0; color: #e0e0e0;
text-align: center; text-align: center;
white-space: pre-line; white-space: pre-line;
} }
} }
} }
&.mobile {
height: auto;
padding: 6rem 0 13rem;
background: url('@/assets/images/mobile_version_background/section_bg.png') no-repeat;
background-size: 100% 100%;
.title {
font-size: 3.2rem;
margin-bottom: 0.8rem;
}
.sub-title {
font-size: 2.4rem;
margin-bottom: 6rem;
}
.criteria-list {
// flex-wrap: wrap;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(2, 1fr);
grid-column-gap: 6rem;
grid-row-gap: 7rem;
.item {
width: 21rem;
height: initial;
&:nth-of-type(3) {
width: 30rem;
height: 36.8rem;
padding: 3.2rem 0;
}
.icon {
width: 16rem;
height: 15.3rem;
}
.name {
font-size: 2.4rem;
margin: 0.8rem 0 1.2rem;
}
}
}
}
} }
</style> </style>