Browse Source

数字动画效果

gcz 1 week ago
parent
commit
c57cc2b8a6
1 changed files with 75 additions and 8 deletions
  1. 75 8
      src/pages/about/Index.vue

+ 75 - 8
src/pages/about/Index.vue

@@ -8,29 +8,29 @@
       <img src="@assets/about-banner-s2.png" alt="" srcset="">
       <img src="@assets/about-banner-s2.png" alt="" srcset="">
 
 
       <!-- 数据模块 -->
       <!-- 数据模块 -->
-      <div class="data-stats">
+      <div class="data-stats" ref="dataStatsRef">
         <div class="stats-item">
         <div class="stats-item">
-          <div class="stats-number">31</div>
+          <div class="stats-number">{{ animatedStats.avgAge }}</div>
           <div class="stats-label">员工平均年龄</div>
           <div class="stats-label">员工平均年龄</div>
         </div>
         </div>
         <div class="stats-divider"></div>
         <div class="stats-divider"></div>
         <div class="stats-item">
         <div class="stats-item">
-          <div class="stats-number">83%</div>
+          <div class="stats-number">{{ animatedStats.education }}%</div>
           <div class="stats-label">本科学历以上占比</div>
           <div class="stats-label">本科学历以上占比</div>
         </div>
         </div>
         <div class="stats-divider"></div>
         <div class="stats-divider"></div>
         <div class="stats-item">
         <div class="stats-item">
-          <div class="stats-number">57%</div>
+          <div class="stats-number">{{ animatedStats.technical }}%</div>
           <div class="stats-label">专业技术人员占比</div>
           <div class="stats-label">专业技术人员占比</div>
         </div>
         </div>
         <div class="stats-divider"></div>
         <div class="stats-divider"></div>
         <div class="stats-item">
         <div class="stats-item">
-          <div class="stats-number">38%</div>
+          <div class="stats-number">{{ animatedStats.professional }}%</div>
           <div class="stats-label">行业专业技术人才占比</div>
           <div class="stats-label">行业专业技术人才占比</div>
         </div>
         </div>
         <div class="stats-divider"></div>
         <div class="stats-divider"></div>
         <div class="stats-item">
         <div class="stats-item">
-          <div class="stats-number">53%</div>
+          <div class="stats-number">{{ animatedStats.senior }}%</div>
           <div class="stats-label">中高级职称人员占比</div>
           <div class="stats-label">中高级职称人员占比</div>
         </div>
         </div>
       </div>
       </div>
@@ -94,9 +94,10 @@
 </template>
 </template>
 
 
 <script>
 <script>
-import { ref, onMounted, computed } from 'vue'
+import { ref, onMounted, computed, onUnmounted } from 'vue'
 import { getCompanyCertList } from '@/api/modules/home'
 import { getCompanyCertList } from '@/api/modules/home'
 import DefaultLayout from '@/layouts/DefaultLayout.vue'
 import DefaultLayout from '@/layouts/DefaultLayout.vue'
+import { animateNumber, createNumberAnimationObserver } from '@/utils/numberAnimation'
 
 
 export default {
 export default {
   name: 'AboutPage',
   name: 'AboutPage',
@@ -117,6 +118,28 @@ export default {
     // 加载状态
     // 加载状态
     const loading = ref(false)
     const loading = ref(false)
 
 
+    // 数据统计相关
+    const dataStatsRef = ref(null)
+    const animationObserver = ref(null)
+    
+    // 动画数字状态
+    const animatedStats = ref({
+      avgAge: 0,
+      education: 0,
+      technical: 0,
+      professional: 0,
+      senior: 0
+    })
+
+    // 目标数字
+    const targetStats = {
+      avgAge: 31,
+      education: 83,
+      technical: 57,
+      professional: 38,
+      senior: 53
+    }
+
     // 证书分类数据
     // 证书分类数据
     const certificateCategories = ref([
     const certificateCategories = ref([
       {
       {
@@ -211,8 +234,49 @@ export default {
       }
       }
     }
     }
 
 
+    // 启动数字动画
+    const startStatsAnimation = () => {
+      // 为每个统计数字创建动画,添加延迟以创建连续效果
+      const delays = [0, 200, 400, 600, 800]
+      
+      Object.keys(targetStats).forEach((key, index) => {
+        setTimeout(() => {
+          animateNumber(
+            (value) => {
+              animatedStats.value[key] = value
+            },
+            targetStats[key],
+            2000 // 2秒动画时长
+          )
+        }, delays[index])
+      })
+    }
+
+    // 设置数字动画观察器
+    const setupStatsAnimation = () => {
+      if (dataStatsRef.value) {
+        animationObserver.value = createNumberAnimationObserver(
+          '.data-stats',
+          startStatsAnimation,
+          {
+            threshold: 0.3,
+            rootMargin: '0px 0px -50px 0px'
+          }
+        )
+      }
+    }
+
     onMounted(() => {
     onMounted(() => {
       loadCertificates()
       loadCertificates()
+      // 延迟设置动画观察器,确保DOM已渲染
+      setTimeout(setupStatsAnimation, 100)
+    })
+
+    onUnmounted(() => {
+      // 清理观察器
+      if (animationObserver.value) {
+        animationObserver.value.disconnect()
+      }
     })
     })
 
 
     return {
     return {
@@ -229,7 +293,10 @@ export default {
       switchTab,
       switchTab,
       prevSlide,
       prevSlide,
       nextSlide,
       nextSlide,
-      handleImageError
+      handleImageError,
+      // 数字动画相关
+      dataStatsRef,
+      animatedStats
     }
     }
   }
   }
 }
 }