不得不说。gsap真好用啊
<template>
<div class="CountDownNumber-container" v-if="visiableModel">
<div class="number-container">
<div v-for="(num, i) in count" :key="num" class="num">
{{ count - i }}
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { gsap } from 'gsap'
defineOptions({
name: 'CountDownNumberCom',
})
const props = defineProps({
visiableModel: {
type: Boolean,
default: false,
},
count: {
type: Number,
default: 3,
},
})
const Emits = defineEmits(['update:visiableModel'])
const countNumber = ref(props.count)
const currentSlide = ref(0)
const slideElement = ref()
watch(
() => props.visiableModel,
(val) => {
if (val) {
nextTick(() => {
slideElement.value = gsap.utils.toArray('.num')
gsap.set(slideElement.value, { y: '100%', opacity: 0 })
gsap.set(slideElement.value[0], { y: '0%', opacity: 1 })
countDownFun()
})
}
},
{ immediate: true },
)
function countDownFun() {
const a = setInterval(() => {
if (countNumber.value > 1) {
// 倒计时到1后就隐藏
countNumber.value--
goToSlide(currentSlide.value + 1)
} else {
Emits('update:visiableModel', false)
clearInterval(a)
}
}, 1000)
}
function goToSlide(index: number) {
console.log(currentSlide.value, index)
if (index === currentSlide.value) return
if (index === props.count) return // 最后一个时不执行滑出动画
// 当前滑出
gsap.to(slideElement.value[currentSlide.value], {
y: '100%',
opacity: 0,
duration: 0.8,
ease: 'power2.inOut',
})
// 新滑入
gsap.fromTo(
slideElement.value[index],
{ y: '-100%', opacity: 0 },
{ y: '0%', opacity: 1, duration: 0.8, ease: 'power2.inOut' },
)
currentSlide.value = index
}
</script>
<style lang="scss" scoped>
.CountDownNumber-container {
height: 100vh;
width: 100vw;
display: flex;
align-items: center;
justify-content: center;
position: fixed;
top: 0;
left: 0;
right: 0;
.number-container {
width: 1018px;
height: 323px;
background: linear-gradient(
269deg,
rgba(97, 160, 255, 0) 0%,
rgba(131, 131, 131, 0.28) 11%,
rgba(70, 70, 70, 0.56) 35%,
rgba(27, 27, 27, 0.56) 61%,
rgba(59, 59, 59, 0.28) 87%,
rgba(97, 160, 255, 0) 100%
);
border-radius: 0px 0px 0px 0px;
overflow: hidden;
position: relative;
.num {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
font-family: 'HYZhengYuan';
font-weight: 800;
font-size: 144px;
color: #ff6363;
text-stroke: 8px #ffffff;
-webkit-text-stroke: 8px #ffffff;
position: absolute;
opacity: 0;
}
}
}
</style>