feat: 平板端适配
This commit is contained in:
BIN
src/assets/images/pad_version/bloom_bg.png
Normal file
BIN
src/assets/images/pad_version/bloom_bg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1005 KiB |
BIN
src/assets/images/pad_version/prizes-bg.png
Normal file
BIN
src/assets/images/pad_version/prizes-bg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 MiB |
BIN
src/assets/images/pad_version/timeline_bg.png
Normal file
BIN
src/assets/images/pad_version/timeline_bg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1015 KiB |
@@ -1,10 +1,11 @@
|
|||||||
export default {
|
export default {
|
||||||
AwardsPage: {
|
AwardsPage: {
|
||||||
submitApplication: 'Submit your Application',
|
submitApplication: 'Submit your Application',
|
||||||
submitMobile:'Apply',
|
submitMobile: 'Apply',
|
||||||
contactUs: 'Contact Us',
|
contactUs: 'Contact Us',
|
||||||
contactHeader: 'We\'re here to help',
|
contactHeader: "We're here to help",
|
||||||
contactDesc:'For questions on eligibility, competition rules,\n judging criteria, or any other enquiries,\n feel free to reach out via our official email.',
|
contactDesc:
|
||||||
|
'For questions on eligibility, competition rules,\n judging criteria, or any other enquiries,\n feel free to reach out via our official email.',
|
||||||
sendEmail: 'Send Email',
|
sendEmail: 'Send Email',
|
||||||
copyMail: 'Successfully copied to clipboard!',
|
copyMail: 'Successfully copied to clipboard!',
|
||||||
sendEmailFailed: 'Failed to open email client, we have copied the email to your clipboard.',
|
sendEmailFailed: 'Failed to open email client, we have copied the email to your clipboard.',
|
||||||
@@ -59,7 +60,7 @@ export default {
|
|||||||
regular2: 'is an ',
|
regular2: 'is an ',
|
||||||
bold2: 'international design competition ',
|
bold2: 'international design competition ',
|
||||||
regular3: 'hosted by ',
|
regular3: 'hosted by ',
|
||||||
bold3: 'Code-Create ',
|
bold3: 'Code-Create',
|
||||||
regular4: ', a globally leading\n',
|
regular4: ', a globally leading\n',
|
||||||
bold4: 'AI fashion solutions provider,',
|
bold4: 'AI fashion solutions provider,',
|
||||||
regular5:
|
regular5:
|
||||||
@@ -72,10 +73,9 @@ export default {
|
|||||||
'participants are invited to transform bold ideas into extraordinary designs, seamlessly merging human artistry with artificial intelligence to shape the next era of fashion.'
|
'participants are invited to transform bold ideas into extraordinary designs, seamlessly merging human artistry with artificial intelligence to shape the next era of fashion.'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
bloomDesc1:
|
bloomDesc1: `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">Code‑Create</span>,\n a globally leading <span class="arial-bold">AI fashion solutions provider</span>, celebrating the future of creativity powered by artificial\nintelligence.Bringing together designers from around the world, AiDA empowers AI as a creative partner\n — pushing fashion beyond traditional boundaries and unlocking new possibilities where technology\namplifies human imagination.`,
|
||||||
'The AiDA Global Design Award 2026 is an\ninternational design competition hosted by\nCode‑Create, a globally leading AI fashion solutions provider,\ncelebrating the future of creativity powered by artificial intelligence.\nBringing together designers from around the world, AiDA empowers AI as a creative partner—pushing fashion beyond traditional boundaries and unlocking new possibilities where technology amplifies human imagination.',
|
|
||||||
bloomDesc2:
|
bloomDesc2:
|
||||||
'Under the theme “Where Imagination Meets Innovation, Creativity Blooms,” participants are invited to transform bold ideas into extraordinary designs, seamlessly merging human artistry with artificial intelligence to shape the next era of fashion.',
|
'Under the theme <span class="arial-bold">“Where Imagination Meets Innovation, Creativity Blooms,”</span> participants are invited \n to transform bold ideas into extraordinary designs, seamlessly merging human artistry with artificial \n intelligence to shape the next era of fashion.',
|
||||||
panelOfJudges: 'Panel of Judges',
|
panelOfJudges: 'Panel of Judges',
|
||||||
expertise: 'Expertise',
|
expertise: 'Expertise',
|
||||||
judgesHat: {
|
judgesHat: {
|
||||||
|
|||||||
@@ -67,6 +67,9 @@ export default {
|
|||||||
'为主题,邀请参赛者将大胆创意转化为非凡设计,\n在 AI 辅助下实现艺术与科技的完美融合。AiDA 鼓励设计师突破常规,挑战时尚边界,\n并通过平台展示才华,与全球同行、行业领袖及 AI 专家建立深度联系,共同探索未来设计的可能。'
|
'为主题,邀请参赛者将大胆创意转化为非凡设计,\n在 AI 辅助下实现艺术与科技的完美融合。AiDA 鼓励设计师突破常规,挑战时尚边界,\n并通过平台展示才华,与全球同行、行业领袖及 AI 专家建立深度联系,共同探索未来设计的可能。'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
bloomDesc1: `AiDA<span class="arial-bold">全球设计奖2026</span>是由全球领先的<span class="arial-bold">AI时尚解决方案提供商Code-Create</span>主办的<span class="arial-bold">国际设计竞赛</span>,\n旨在庆祝人工智能赋能下的未来创意。该赛事汇聚来自世界各地的设计师,将<span class="arial-bold">AI视为创意伙伴</span>,\n突破传统时尚边界,探索技术与人类想象力结合的无限可能。`,
|
||||||
|
bloomDesc2:
|
||||||
|
'本届大赛以"想象遇见创新,创意绽放"为主题,邀请参赛者将大胆创意转化为非凡设计,\n在 AI 辅助下实现艺术与科技的完美融合,共同探索未来设计的可能。',
|
||||||
panelOfJudges: '终审评委团',
|
panelOfJudges: '终审评委团',
|
||||||
expertise: '权威阵容',
|
expertise: '权威阵容',
|
||||||
judgesHat: {
|
judgesHat: {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
class="apply-container flex flex-col"
|
class="apply-container flex flex-col"
|
||||||
id="apply"
|
id="apply"
|
||||||
ref="applyRef"
|
ref="applyRef"
|
||||||
:class="{ mobile: isMobile }"
|
:class="{ mobile: isMobile && !isPad, 'is-pad': isPad }"
|
||||||
>
|
>
|
||||||
<div class="title animation-element" ref="applyTitleRef">
|
<div class="title animation-element" ref="applyTitleRef">
|
||||||
{{ $t('AwardsPage.howToApply') }}
|
{{ $t('AwardsPage.howToApply') }}
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
{{ $t('AwardsPage.stepByStep') }}
|
{{ $t('AwardsPage.stepByStep') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="requirments-list flex flex-col" ref="reqListRef">
|
<div class="requirments-list flex flex-col" ref="reqListRef">
|
||||||
<div class="top flex" :class="{ 'flex-col': isMobile }">
|
<div class="top flex" :class="{ 'flex-col': isMobile && !isPad }">
|
||||||
<div
|
<div
|
||||||
class="item-box animation-element"
|
class="item-box animation-element"
|
||||||
v-for="(item, index) in leftRequirment"
|
v-for="(item, index) in leftRequirment"
|
||||||
@@ -27,7 +27,10 @@
|
|||||||
<div class="item-header flex flex-center">
|
<div class="item-header flex flex-center">
|
||||||
<div class="item-title">{{ $t(item.type) }}</div>
|
<div class="item-title">{{ $t(item.type) }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="context-container flex flex-center" :class="{ 'flex-col': isMobile }">
|
<div
|
||||||
|
class="context-container flex flex-center"
|
||||||
|
:class="{ 'flex-col': isMobile && !isPad }"
|
||||||
|
>
|
||||||
<div class="context" v-for="el in item.desc">
|
<div class="context" v-for="el in item.desc">
|
||||||
{{ $t(el) }}
|
{{ $t(el) }}
|
||||||
</div>
|
</div>
|
||||||
@@ -42,10 +45,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bottom flex" :class="{ 'flex-col': isMobile }">
|
<div class="bottom flex" :class="{ 'flex-col': isMobile && !isPad }">
|
||||||
<div class="step-3 flex flex-col animation-element" ref="step3Ref">
|
<div class="step-3 flex flex-col animation-element" ref="step3Ref">
|
||||||
<div class="header">{{ $t('AwardsPage.step3Title') }}</div>
|
<div class="header">{{ $t('AwardsPage.step3Title') }}</div>
|
||||||
<div class="content flex" :class="{ 'flex-col': isMobile }">
|
<div class="content flex" :class="{ 'flex-col': isMobile && !isPad }">
|
||||||
<div class="content-left flex flex-col space-between">
|
<div class="content-left flex flex-col space-between">
|
||||||
<div class="content-item">
|
<div class="content-item">
|
||||||
<div class="item-header flex align-center">
|
<div class="item-header flex align-center">
|
||||||
@@ -67,7 +70,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content-item" v-if="!isMobile">
|
<div class="content-item" v-if="!(isMobile && !isPad)">
|
||||||
<div class="item-header flex align-center">
|
<div class="item-header flex align-center">
|
||||||
<div class="point"></div>
|
<div class="point"></div>
|
||||||
<div>{{ $t('AwardsPage.fileName') }}</div>
|
<div>{{ $t('AwardsPage.fileName') }}</div>
|
||||||
@@ -108,7 +111,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content-item file" v-if="isMobile">
|
<div class="content-item file" v-if="isMobile && !isPad">
|
||||||
<div class="item-header flex align-center">
|
<div class="item-header flex align-center">
|
||||||
<div class="point"></div>
|
<div class="point"></div>
|
||||||
<div>{{ $t('AwardsPage.fileName') }}</div>
|
<div>{{ $t('AwardsPage.fileName') }}</div>
|
||||||
@@ -156,7 +159,7 @@ import { gsap } from 'gsap'
|
|||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const isMobile = inject<boolean>('isMobile')
|
const isMobile = inject<boolean>('isMobile')
|
||||||
|
const isPad = inject<boolean>('isPad')
|
||||||
const leftRequirment = ref([
|
const leftRequirment = ref([
|
||||||
{
|
{
|
||||||
type: 'AwardsPage.step1Title',
|
type: 'AwardsPage.step1Title',
|
||||||
@@ -456,6 +459,7 @@ ul {
|
|||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 2.4rem;
|
font-size: 2.4rem;
|
||||||
color: #585858;
|
color: #585858;
|
||||||
|
white-space: pre-line;
|
||||||
&.indent {
|
&.indent {
|
||||||
padding-left: 3.8rem;
|
padding-left: 3.8rem;
|
||||||
line-height: 3rem;
|
line-height: 3rem;
|
||||||
@@ -473,12 +477,11 @@ ul {
|
|||||||
line-height: 3rem;
|
line-height: 3rem;
|
||||||
row-gap: 3rem;
|
row-gap: 3rem;
|
||||||
.desc-lists {
|
.desc-lists {
|
||||||
/* 使用自定义方块代替浏览器 marker,保证大小为 1rem 并与文字垂直居中 */
|
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
li {
|
li {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
/* 使内容对齐到首行顶部,方块通过 margin-top 调整到首行中间 */
|
white-space: pre-line;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
@@ -486,13 +489,11 @@ ul {
|
|||||||
margin: 0.4rem 0;
|
margin: 0.4rem 0;
|
||||||
&::before {
|
&::before {
|
||||||
content: '';
|
content: '';
|
||||||
/* 固定为 1rem 方块 */
|
|
||||||
width: 0.5rem;
|
width: 0.5rem;
|
||||||
height: 0.5rem;
|
height: 0.5rem;
|
||||||
background-color: #585858;
|
background-color: #585858;
|
||||||
flex: 0 0 0.5rem;
|
flex: 0 0 0.5rem;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
/* 让方块垂直居中于第一行文字:(line-height - square)/2 */
|
|
||||||
margin-top: calc((var(--desc-line-height, 3rem) - 1rem) / 2);
|
margin-top: calc((var(--desc-line-height, 3rem) - 1rem) / 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -637,5 +638,25 @@ ul {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&.is-pad {
|
||||||
|
height: auto;
|
||||||
|
.top {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
.bottom {
|
||||||
|
height: auto;
|
||||||
|
flex-direction: column;
|
||||||
|
.content-item {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
.step-4 {
|
||||||
|
margin-top: 4rem;
|
||||||
|
width: 100%;
|
||||||
|
.desc-lists li{
|
||||||
|
white-space: initial !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="bloom flex flex-col align-center" :class="{ mobile: isMobile }">
|
<div class="bloom flex flex-col align-center" :class="{ mobile: isMobile, pad: isPad }">
|
||||||
<div class="title" ref="titleRef">
|
<div class="title" ref="titleRef">
|
||||||
{{ $t('AwardsPage.bloomYourCreativity') }}
|
{{ $t('AwardsPage.bloomYourCreativity') }}
|
||||||
</div>
|
</div>
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
</span>
|
</span>
|
||||||
{{ $t('AwardsPage.bloomText.desc1.regular5') }}
|
{{ $t('AwardsPage.bloomText.desc1.regular5') }}
|
||||||
</p>
|
</p>
|
||||||
|
<!-- <p class="section-1 pad" v-show="isPad" v-html="padSection1"></p> -->
|
||||||
<p class="section-2">
|
<p class="section-2">
|
||||||
{{ $t('AwardsPage.bloomText.desc2.regular1') }}
|
{{ $t('AwardsPage.bloomText.desc2.regular1') }}
|
||||||
<span class="arial-bold">
|
<span class="arial-bold">
|
||||||
@@ -45,11 +46,16 @@ import { gsap } from 'gsap'
|
|||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const isMobile = inject<boolean>('isMobile')
|
const isMobile = inject<boolean>('isMobile')
|
||||||
|
const isPad = inject<boolean>('isPad')
|
||||||
|
|
||||||
const titleRef = ref<HTMLElement | null>(null)
|
const titleRef = ref<HTMLElement | null>(null)
|
||||||
const subtitleRef = ref<HTMLElement | null>(null)
|
const subtitleRef = ref<HTMLElement | null>(null)
|
||||||
const textRef = ref<HTMLElement | null>(null)
|
const textRef = ref<HTMLElement | null>(null)
|
||||||
|
|
||||||
|
// const padSection1 = computed(() => {
|
||||||
|
// return t('AwardsPage.bloomDesc1')
|
||||||
|
// })
|
||||||
|
|
||||||
const hasPlayedBloomAnim = ref(false)
|
const hasPlayedBloomAnim = ref(false)
|
||||||
let bloomObserver: IntersectionObserver | null = null
|
let bloomObserver: IntersectionObserver | null = null
|
||||||
|
|
||||||
@@ -149,8 +155,8 @@ p {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
.arial-bold {
|
:deep(.arial-bold) {
|
||||||
font-family: 'ArialBold';
|
font-family: 'ArialBold', Arial, sans-serif;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
.bloom {
|
.bloom {
|
||||||
@@ -191,7 +197,6 @@ p {
|
|||||||
&.mobile {
|
&.mobile {
|
||||||
background: url('@/assets/images/mobile_version_background/bloom_bg.png') no-repeat;
|
background: url('@/assets/images/mobile_version_background/bloom_bg.png') no-repeat;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
// height: 83.1rem;
|
|
||||||
height: 110vw;
|
height: 110vw;
|
||||||
padding-top: 6rem;
|
padding-top: 6rem;
|
||||||
.title {
|
.title {
|
||||||
@@ -203,11 +208,22 @@ p {
|
|||||||
margin-bottom: 6.2rem;
|
margin-bottom: 6.2rem;
|
||||||
}
|
}
|
||||||
.desc {
|
.desc {
|
||||||
// padding: 0 6.5rem 0 6.7rem;
|
|
||||||
padding: 0 8.5vw;
|
padding: 0 8.5vw;
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
line-height: 3rem;
|
line-height: 3rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&.pad {
|
||||||
|
height: 84.6vw;
|
||||||
|
background: url('@/assets/images/pad_version/bloom_bg.png') no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
.arial-bold {
|
||||||
|
font-family: 'ArialBold';
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
.desc {
|
||||||
|
// font-size: 2.4rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="judges-container flex flex-col align-center" :class="{ mobile: isMobile }">
|
<div class="judges-container flex flex-col align-center" :class="{ mobile: isMobile && !isPad }">
|
||||||
<div class="title" ref="judgesTitleRef">{{ $t('AwardsPage.panelOfJudges') }}</div>
|
<div class="title" ref="judgesTitleRef">{{ $t('AwardsPage.panelOfJudges') }}</div>
|
||||||
<!-- <img src="@/assets/images/award/bloom_logo.png" class="logo" /> -->
|
<!-- <img src="@/assets/images/award/bloom_logo.png" class="logo" /> -->
|
||||||
<div class="sub-title" ref="judgesSubTitleRef">{{ $t('AwardsPage.expertise') }}</div>
|
<div class="sub-title" ref="judgesSubTitleRef">{{ $t('AwardsPage.expertise') }}</div>
|
||||||
@@ -30,6 +30,7 @@ import desmond from '@/assets/images/award/desmond.png'
|
|||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const isMobile = inject<boolean>('isMobile')
|
const isMobile = inject<boolean>('isMobile')
|
||||||
|
const isPad = inject<boolean>('isPad')
|
||||||
const judgements = [
|
const judgements = [
|
||||||
{
|
{
|
||||||
picture: jae,
|
picture: jae,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div
|
<div
|
||||||
class="prizes-container container flex align-center space-between"
|
class="prizes-container container flex align-center space-between"
|
||||||
ref="prizesRef"
|
ref="prizesRef"
|
||||||
:class="{ mobile: isMobile, 'flex-col': isMobile }"
|
:class="{ mobile: isMobile && !isPad, 'flex-col': isMobile && !isPad, 'is-pad': isPad }"
|
||||||
>
|
>
|
||||||
<div class="left flex flex-col flex-center">
|
<div class="left flex flex-col flex-center">
|
||||||
<div class="title" ref="prizesTitleRef">
|
<div class="title" ref="prizesTitleRef">
|
||||||
@@ -41,6 +41,7 @@ import { gsap } from 'gsap'
|
|||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const isMobile = inject<boolean>('isMobile')
|
const isMobile = inject<boolean>('isMobile')
|
||||||
|
const isPad = inject<boolean>('isPad')
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
isZh: {
|
isZh: {
|
||||||
@@ -283,5 +284,12 @@ onBeforeUnmount(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&.is-pad {
|
||||||
|
background: url('@/assets/images/pad_version/prizes-bg.png') no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
padding: 0 6rem;
|
||||||
|
justify-content: center;
|
||||||
|
column-gap: 10rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="blocks-list flex" ref="root" :class="{ 'in-view': inView }">
|
<div class="blocks-list flex" ref="root" :class="{ 'in-view': inView, mobile: isMobile }">
|
||||||
<div
|
<div
|
||||||
class="block-item flex flex-col flex-center"
|
class="block-item flex flex-col flex-center"
|
||||||
v-for="(item, idx) in blocksList"
|
v-for="(item, idx) in blocksList"
|
||||||
@@ -14,11 +14,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, onMounted, onUnmounted } from 'vue'
|
import { computed, ref, onMounted, onUnmounted, inject } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
const isMobile = inject('isMobile')
|
||||||
const blocksList = ref([
|
const blocksList = ref([
|
||||||
{
|
{
|
||||||
number: 'AwardsPage.totalCashPrizes',
|
number: 'AwardsPage.totalCashPrizes',
|
||||||
@@ -151,7 +151,7 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 移动端 <= 1200px 四宫格布局 */
|
/* 移动端 <= 1200px 四宫格布局 */
|
||||||
@media (max-width: 1200px) {
|
.mobile {
|
||||||
.blocks-list {
|
.blocks-list {
|
||||||
height: auto;
|
height: auto;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|||||||
@@ -2,17 +2,13 @@
|
|||||||
<div
|
<div
|
||||||
ref="containerRef"
|
ref="containerRef"
|
||||||
class="timeline-container container flex flex-col align-center"
|
class="timeline-container container flex flex-col align-center"
|
||||||
:class="{ mobile: isMobileOrNarrow, vertical: isMobile }"
|
:class="{ mobile: isMobile && !isPad, vertical: isMobile && !isPad ,'is-pad': isPad}"
|
||||||
>
|
>
|
||||||
<div class="timeline-title">{{ $t('AwardsPage.competitionTimeline') }}</div>
|
<div class="timeline-title">{{ $t('AwardsPage.competitionTimeline') }}</div>
|
||||||
<div class="desc">{{ $t('AwardsPage.shapingTheFuture') }}</div>
|
<div class="desc">{{ $t('AwardsPage.shapingTheFuture') }}</div>
|
||||||
|
|
||||||
<!-- 纵向时间线:移动端或宽度 <= 1200px -->
|
<!-- 纵向时间线:移动端(排除平板) -->
|
||||||
<div
|
<div v-if="isMobile && !isPad" class="timeline-point timeline-vertical flex flex-col" ref="timelineRef">
|
||||||
v-if="isMobile"
|
|
||||||
class="timeline-point timeline-vertical flex flex-col"
|
|
||||||
ref="timelineRef"
|
|
||||||
>
|
|
||||||
<div class="vertical-line"></div>
|
<div class="vertical-line"></div>
|
||||||
<div v-for="(item, index) in points" :key="'vertical-' + item.time" class="vertical-item">
|
<div v-for="(item, index) in points" :key="'vertical-' + item.time" class="vertical-item">
|
||||||
<div class="vertical-node">
|
<div class="vertical-node">
|
||||||
@@ -71,9 +67,10 @@ import { gsap } from 'gsap'
|
|||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
const isMobile = inject<boolean>('isMobile')
|
const isMobile = inject<boolean>('isMobile')
|
||||||
|
const isPad = inject<boolean>('isPad')
|
||||||
const windowWidth = ref(typeof window !== 'undefined' ? window.innerWidth : 1201)
|
const windowWidth = ref(typeof window !== 'undefined' ? window.innerWidth : 1201)
|
||||||
|
|
||||||
const isMobileOrNarrow = computed(() => isMobile.value)
|
const isMobileOrNarrow = computed(() => isMobile.value && !isPad.value)
|
||||||
|
|
||||||
const updateWindowWidth = () => {
|
const updateWindowWidth = () => {
|
||||||
windowWidth.value = window.innerWidth
|
windowWidth.value = window.innerWidth
|
||||||
@@ -122,7 +119,7 @@ const playAnimation = () => {
|
|||||||
const subtitle = containerRef.value.querySelector('.desc')
|
const subtitle = containerRef.value.querySelector('.desc')
|
||||||
const timeline = containerRef.value.querySelector('.timeline-point')
|
const timeline = containerRef.value.querySelector('.timeline-point')
|
||||||
const line = containerRef.value.querySelector(
|
const line = containerRef.value.querySelector(
|
||||||
isMobile.value ? '.vertical-line' : '.timeline-line'
|
isMobile.value && !isPad.value ? '.vertical-line' : '.timeline-line'
|
||||||
)
|
)
|
||||||
|
|
||||||
const tl = gsap.timeline()
|
const tl = gsap.timeline()
|
||||||
@@ -130,7 +127,7 @@ const playAnimation = () => {
|
|||||||
|
|
||||||
// 整体 timeline 的裁剪展开(仅横向使用)
|
// 整体 timeline 的裁剪展开(仅横向使用)
|
||||||
// 纵向时跳过裁剪动画,改用每个 item 从上方落下的动画
|
// 纵向时跳过裁剪动画,改用每个 item 从上方落下的动画
|
||||||
if (timeline && !isMobile.value) {
|
if (timeline && !(isMobile.value && !isPad.value)) {
|
||||||
tl.fromTo(
|
tl.fromTo(
|
||||||
timeline,
|
timeline,
|
||||||
{
|
{
|
||||||
@@ -148,7 +145,7 @@ const playAnimation = () => {
|
|||||||
// 线条动画:横向 scaleX,纵向 scaleY
|
// 线条动画:横向 scaleX,纵向 scaleY
|
||||||
// 纵向时线条与 item 动画同步进行
|
// 纵向时线条与 item 动画同步进行
|
||||||
if (line) {
|
if (line) {
|
||||||
if (isMobile.value) {
|
if (isMobile.value && !isPad.value) {
|
||||||
tl.from(
|
tl.from(
|
||||||
line,
|
line,
|
||||||
{
|
{
|
||||||
@@ -191,11 +188,11 @@ const playAnimation = () => {
|
|||||||
|
|
||||||
// 行内内容:桌面端用 .grid-cell,纵向用 .vertical-item
|
// 行内内容:桌面端用 .grid-cell,纵向用 .vertical-item
|
||||||
// 纵向时,每个 item 从上方落下 + 渐显
|
// 纵向时,每个 item 从上方落下 + 渐显
|
||||||
const textItems = isMobile.value
|
const textItems = isMobile.value && !isPad.value
|
||||||
? containerRef.value.querySelectorAll('.vertical-item')
|
? containerRef.value.querySelectorAll('.vertical-item')
|
||||||
: containerRef.value.querySelectorAll('.grid-cell')
|
: containerRef.value.querySelectorAll('.grid-cell')
|
||||||
if (textItems && textItems.length) {
|
if (textItems && textItems.length) {
|
||||||
if (isMobile.value) {
|
if (isMobile.value && !isPad.value) {
|
||||||
// 纵向:每个 item 从上方落下 + 渐显
|
// 纵向:每个 item 从上方落下 + 渐显
|
||||||
tl.from(
|
tl.from(
|
||||||
textItems,
|
textItems,
|
||||||
@@ -510,5 +507,9 @@ onBeforeUnmount(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&.is-pad {
|
||||||
|
background: url('@/assets/images/pad_version/timeline_bg.png') no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, onMounted, provide } from 'vue'
|
import { ref, computed, onMounted, provide,onUnmounted } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import JudgesSection from './components/JudgesSection.vue'
|
import JudgesSection from './components/JudgesSection.vue'
|
||||||
@@ -50,10 +50,26 @@ const { locale } = useI18n()
|
|||||||
|
|
||||||
provide('isMobile', isMobile)
|
provide('isMobile', isMobile)
|
||||||
|
|
||||||
|
const isPad = ref(false)
|
||||||
|
provide('isPad', isPad)
|
||||||
|
|
||||||
|
const checkIsPad = () => {
|
||||||
|
const ua = navigator.userAgent.toLowerCase()
|
||||||
|
const padRegex = /ipad|tablet|playbook|silk/i
|
||||||
|
const isPadUA = padRegex.test(ua)
|
||||||
|
const isPadWidth = window.innerWidth > 768 && window.innerWidth <= 1200
|
||||||
|
isPad.value = isPadUA || isPadWidth
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
checkIsPad()
|
||||||
|
window.addEventListener('resize', checkIsPad)
|
||||||
router.replace('/')
|
router.replace('/')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
window.removeEventListener('resize', checkIsPad)
|
||||||
|
})
|
||||||
const isZh = computed(() => {
|
const isZh = computed(() => {
|
||||||
return locale.value === 'CHINESE_SIMPLIFIED'
|
return locale.value === 'CHINESE_SIMPLIFIED'
|
||||||
})
|
})
|
||||||
@@ -61,12 +77,10 @@ const isZh = computed(() => {
|
|||||||
const bannerUrl = computed(() => {
|
const bannerUrl = computed(() => {
|
||||||
let url = null
|
let url = null
|
||||||
if (isMobile.value) {
|
if (isMobile.value) {
|
||||||
console.log('移动端-----------')
|
|
||||||
url = isZh.value ? bannerZhMobile : bannerMobile
|
url = isZh.value ? bannerZhMobile : bannerMobile
|
||||||
} else {
|
} else {
|
||||||
url = isZh.value ? bannerZh : banner
|
url = isZh.value ? bannerZh : banner
|
||||||
}
|
}
|
||||||
console.log('url-----------', url)
|
|
||||||
|
|
||||||
return url
|
return url
|
||||||
})
|
})
|
||||||
@@ -147,9 +161,11 @@ const handleSubmitApplication = () => {
|
|||||||
.banner.mobile {
|
.banner.mobile {
|
||||||
height: auto;
|
height: auto;
|
||||||
.submit-btn {
|
.submit-btn {
|
||||||
top: 48%;
|
top: 52%;
|
||||||
left: 8%;
|
left: 8%;
|
||||||
width: 48rem;
|
width: 41rem;
|
||||||
|
font-size: 2.4rem;
|
||||||
|
column-gap: 1rem;
|
||||||
.ddl {
|
.ddl {
|
||||||
white-space: pre-line;
|
white-space: pre-line;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
|||||||
Reference in New Issue
Block a user