feat(components): 优化数字滚动效果并添加循环播放控制
- 在 CountTo 组件中添加 update:readyLoop 事件,用于通知数字滚动完成 - 在 Header 组件中使用 readyLoop 事件来控制 Swiper 轮播的初始化和销毁 - 优化了数字滚动的动画效果,确保滚动到目标数字后停止
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<span class="count-to">{{ formattedCount }}</span>
|
||||
<span class="count-to">{{ formattedCount }} </span>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@@ -20,6 +20,7 @@ const props = defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:readyLoop'])
|
||||
// 工具函数:将 "1,000" 转成 1000
|
||||
const parseValue = (val) => {
|
||||
if (typeof val === 'number') return val
|
||||
@@ -42,6 +43,9 @@ const formattedCount = ref('0')
|
||||
|
||||
const animateCount = () => {
|
||||
parsedEnd.value = parseValue(props.end)
|
||||
|
||||
|
||||
formattedCount.value = props.end
|
||||
let start = 0
|
||||
const totalSteps = Math.round(props.duration / 16)
|
||||
const increment = parsedEnd.value / totalSteps
|
||||
@@ -50,7 +54,8 @@ const animateCount = () => {
|
||||
start += increment
|
||||
if (start >= parsedEnd.value) {
|
||||
currentCount.value = parsedEnd.value
|
||||
formattedCount.value = props.useComma ? formatWithCommas(parsedEnd.value) : parsedEnd.value
|
||||
formattedCount.value = props.useComma ? formatWithCommas(parsedEnd.value) : parsedEnd.value
|
||||
emit('readyLoop')
|
||||
return
|
||||
}
|
||||
currentCount.value = Math.round(start)
|
||||
@@ -71,6 +76,10 @@ watch(
|
||||
() => props.end,
|
||||
() => {
|
||||
animateCount()
|
||||
},
|
||||
{
|
||||
deep:true,
|
||||
immediate:true
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
@@ -5,12 +5,14 @@
|
||||
<!-- Swiper 轮播容器 -->
|
||||
<div class="swiper-container" ref="swiperContainer">
|
||||
<div class="swiper-wrapper">
|
||||
<div class="banner-block swiper-slide">
|
||||
<div class="banner-block swiper-slide" :key="surveyStats.user_count">
|
||||
<p class="banner-block-slogan">实时链接消费者的深度洞察及日常信息采集工具</p>
|
||||
<div class="banner-block-desc">
|
||||
已支持 <CountTo :end="surveyStats.user_count" :use-comma="true" /> 用户 |
|
||||
发起 <CountTo :end="surveyStats.survey_count" :use-comma="true" /> 次调研 |
|
||||
有效回收 <CountTo :end="surveyStats.sample_count" :use-comma="true" /> 份数据
|
||||
已支持 <CountTo :end="surveyStats.user_count" :use-comma="true" :key="surveyStats.user_count"
|
||||
@ready-loop="readyLoop"
|
||||
/> 用户 |
|
||||
发起 <CountTo :end="surveyStats.survey_count" :use-comma="true" @ready-loop="readyLoop" /> 次调研 |
|
||||
有效回收 <CountTo :end="surveyStats.sample_count" :use-comma="true" @ready-loop="readyLoop" /> 份数据
|
||||
</div>
|
||||
</div>
|
||||
<!-- 动态 Banner 列表 -->
|
||||
@@ -60,7 +62,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onBeforeUnmount, onMounted, ref } from 'vue';
|
||||
import { onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
||||
import Swiper, { Autoplay } from 'swiper';
|
||||
import 'swiper/swiper-bundle.css';
|
||||
import { useRouter } from 'vue-router';
|
||||
@@ -105,10 +107,22 @@ const getQuesStatics = async () => {
|
||||
const res = await getQuestionnaireStatistics()
|
||||
surveyData.value = res.data
|
||||
}
|
||||
const initSwiper = ()=>{
|
||||
|
||||
const readyLoop = ()=>{
|
||||
if (bannerSwiper){
|
||||
bannerSwiper.destroy()
|
||||
}
|
||||
initSwiper(true)
|
||||
}
|
||||
|
||||
const initSwiper = (loop = false)=>{
|
||||
// 初始化 Swiper
|
||||
if (bannerSwiper) {
|
||||
bannerSwiper.destroy(true, true);
|
||||
bannerSwiper = null;
|
||||
}
|
||||
bannerSwiper = new Swiper(swiperContainer.value, {
|
||||
loop: true,
|
||||
loop,
|
||||
autoplay: {
|
||||
delay: 5000,
|
||||
disableOnInteraction: false
|
||||
|
||||
Reference in New Issue
Block a user