From e4bdfcb0571b51b4d1d55f99df1d1f8ed21c35e3 Mon Sep 17 00:00:00 2001
From: 刘嘉威 <daidaibg@163.com>
Date: 星期一, 17 十月 2022 11:29:36 +0800
Subject: [PATCH] feat: 增加数字滚动组件 展示时间显示
---
src/components/count-up/count-up.vue | 146 ++++++++++++++++++++++++++++++++++++
src/views/HomeView.vue | 2
package-lock.json | 10 ++
src/components/count-up/index.ts | 3
src/components/scale-screen/scale-screen.vue | 2
package.json | 2
src/views/header.vue | 23 ++++-
src/views/index.d.ts | 27 ++++++
src/assets/css/main.scss | 4
9 files changed, 209 insertions(+), 10 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 01ce7d9..c03dd20 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -520,6 +520,11 @@
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true
},
+ "countup.js": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/countup.js/-/countup.js-2.3.2.tgz",
+ "integrity": "sha512-dQ7F/CmKGjaO6cDfhtEXwsKVlXIpJ89dFs8PvkaZH9jBVJ2Z8GU4iwG/qP7MgY8qwr+1skbwR6qecWWQLUzB8Q=="
+ },
"cross-spawn": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
@@ -544,6 +549,11 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz",
"integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w=="
},
+ "dayjs": {
+ "version": "1.11.5",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.5.tgz",
+ "integrity": "sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA=="
+ },
"de-indent": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
diff --git a/package.json b/package.json
index 2091954..f33d400 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,8 @@
},
"dependencies": {
"axios": "^1.1.2",
+ "countup.js": "^2.3.2",
+ "dayjs": "^1.11.5",
"echarts": "^5.4.0",
"mockjs": "^1.1.0",
"pinia": "^2.0.21",
diff --git a/src/assets/css/main.scss b/src/assets/css/main.scss
index 20f90dd..2e0cbef 100644
--- a/src/assets/css/main.scss
+++ b/src/assets/css/main.scss
@@ -3,5 +3,7 @@
width: 100%;
}
#app{
-
+ .content_wrap{
+ color: #d3d6dd;
+ }
}
\ No newline at end of file
diff --git a/src/components/count-up/count-up.vue b/src/components/count-up/count-up.vue
new file mode 100644
index 0000000..2f07b0e
--- /dev/null
+++ b/src/components/count-up/count-up.vue
@@ -0,0 +1,146 @@
+<script lang="ts">
+export type { CountUp as ICountUp, CountUpOptions } from 'countup.js'
+export default {
+ name: 'CountUp'
+}
+</script>
+<script setup lang="ts">
+import { onMounted, onUnmounted, ref, watch } from 'vue'
+import { CountUp } from 'countup.js'
+import type { CountUpOptions } from 'countup.js'
+
+const props = withDefaults(
+ defineProps<{
+ // 缁撴潫鏁板��
+ endVal: number | string
+ // 寮�濮嬫暟鍊�
+ startVal?: number | string
+ // 鍔ㄧ敾鏃堕暱锛屽崟浣� s
+ duration?: number | string
+ // 鏄惁鑷姩璁℃暟
+ autoplay?: boolean
+ // 寰幆娆℃暟锛屾湁闄愭鏁� / 鏃犻檺寰幆
+ loop?: boolean | number | string
+ // 寤舵椂锛屽崟浣� s
+ delay?: number
+ // countup 閰嶇疆椤�
+ options?: CountUpOptions
+ }>(),
+ {
+ startVal: 0,
+ duration: 2.5,
+ autoplay: true,
+ loop: false,
+ delay: 0,
+ options: undefined
+ }
+)
+const emits = defineEmits<{
+ // countup init complete
+ (event: 'init', countup: CountUp): void
+ // count complete
+ (event: 'finished'): void
+}>()
+
+let elRef = ref<HTMLElement>()
+let countUp = ref<CountUp>()
+
+const initCountUp = () => {
+ if (!elRef.value) return
+ const startVal = Number(props.startVal)
+ const endVal = Number(props.endVal)
+ const duration = Number(props.duration)
+ countUp.value = new CountUp(elRef.value, endVal, {
+ startVal,
+ duration,
+ ...props.options
+ })
+ if (countUp.value.error) {
+ console.error(countUp.value.error)
+ return
+ }
+ emits('init', countUp.value)
+}
+
+const startAnim = (cb?: () => void) => {
+ countUp.value?.start(cb)
+}
+
+// endVal change & autoplay: true, restart animate
+watch(
+ () => props.endVal,
+ (value) => {
+ if (props.autoplay) {
+ countUp.value?.update(value)
+ }
+ }
+)
+
+// loop animation
+const finished = ref(false)
+let loopCount = 0
+const loopAnim = () => {
+ loopCount++
+ startAnim(() => {
+ const isTruely = typeof props.loop === 'boolean' && props.loop
+ if (isTruely || props.loop > loopCount) {
+ delay(() => {
+ countUp.value?.reset()
+ loopAnim()
+ }, props.delay)
+ } else {
+ finished.value = true
+ }
+ })
+}
+watch(finished, (flag) => {
+ if (flag) {
+ emits('finished')
+ }
+})
+
+onMounted(() => {
+ initCountUp()
+ if (props.autoplay) {
+ loopAnim()
+ }
+})
+onUnmounted(() => {
+ cancelAnimationFrame(dalayRafId)
+ countUp.value?.reset()
+})
+
+let dalayRafId: number
+// delay to execute callback function
+const delay = (cb: () => unknown, seconds = 1) => {
+ let startTime: number
+ function count(timestamp: number) {
+ if (!startTime) startTime = timestamp
+ const diff = timestamp - startTime
+ if (diff < seconds * 1000) {
+ dalayRafId = requestAnimationFrame(count)
+ } else {
+ cb()
+ }
+ }
+ dalayRafId = requestAnimationFrame(count)
+}
+
+const restart = () => {
+ initCountUp()
+ startAnim()
+}
+
+defineExpose({
+ init: initCountUp,
+ restart
+})
+</script>
+
+<template>
+ <div class="countup-wrap">
+ <slot name="prefix"></slot>
+ <span ref="elRef"> </span>
+ <slot name="suffix"></slot>
+ </div>
+</template>
diff --git a/src/components/count-up/index.ts b/src/components/count-up/index.ts
new file mode 100644
index 0000000..567dc07
--- /dev/null
+++ b/src/components/count-up/index.ts
@@ -0,0 +1,3 @@
+import CountUp from "./count-up.vue"
+export default CountUp
+
diff --git a/src/components/scale-screen/scale-screen.vue b/src/components/scale-screen/scale-screen.vue
index 4420bab..9c4395d 100644
--- a/src/components/scale-screen/scale-screen.vue
+++ b/src/components/scale-screen/scale-screen.vue
@@ -19,7 +19,7 @@
* @returns {() => void}
*/
function debounce(fn: Function, delay: number): () => void {
- // let timer: NodeJS.Timeout;
+ // let timer: NodeJS.Timer;
let timer: any;
return function (...args: any[]): void {
if (timer) clearTimeout(timer);
diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue
index 1372464..1de65e4 100644
--- a/src/views/HomeView.vue
+++ b/src/views/HomeView.vue
@@ -11,7 +11,7 @@
height="1080"
:delay="500"
:fullScreen="false"
- :boxStyle="{ background: '#000' }"
+ :boxStyle="{ background: '#03050C' }"
:wrapperStyle="wrapperStyle"
>
<div class="content_wrap">
diff --git a/src/views/header.vue b/src/views/header.vue
index 8ffc87f..aba80ff 100644
--- a/src/views/header.vue
+++ b/src/views/header.vue
@@ -1,13 +1,22 @@
<script setup lang="ts">
import { reactive } from "vue";
-
-const dateData = reactive({
- dateDay: null,
- dateYear: null,
- dateWeek: null,
- weekday: ["鍛ㄦ棩", "鍛ㄤ竴", "鍛ㄤ簩", "鍛ㄤ笁", "鍛ㄥ洓", "鍛ㄤ簲", "鍛ㄥ叚"],
+import dayjs from 'dayjs';
+import type {DateDataType} from "./index.d"
+const dateData = reactive<DateDataType>({
+ dateDay: "",
+ dateYear: "",
+ dateWeek: "",
+ timing:null
});
-
+
+const weekday= ["鍛ㄦ棩", "鍛ㄤ竴", "鍛ㄤ簩", "鍛ㄤ笁", "鍛ㄥ洓", "鍛ㄤ簲", "鍛ㄥ叚"]
+const timeFn = () => {
+ dateData.timing = setInterval(() => {
+ dateData.dateDay = dayjs().format("YYYY-MM-DD hh : mm : ss");
+ dateData.dateWeek = weekday[dayjs().day()];
+ }, 1000);
+};
+timeFn()
const showSetting = () => {};
</script>
diff --git a/src/views/index.d.ts b/src/views/index.d.ts
new file mode 100644
index 0000000..594c11e
--- /dev/null
+++ b/src/views/index.d.ts
@@ -0,0 +1,27 @@
+export interface DateDataType {
+ dateDay: string,
+ dateYear: string,
+ dateWeek: string,
+ timing: NodeJS.Timer
+}
+
+interface CountUpOptions {
+ startVal?: number; // number to start at (0)
+ decimalPlaces?: number; // number of decimal places (0)
+ duration?: number; // animation duration in seconds (2)
+ useGrouping?: boolean; // example: 1,000 vs 1000 (true)
+ useEasing?: boolean; // ease animation (true)
+ smartEasingThreshold?: number; // smooth easing for large numbers above this if useEasing (999)
+ smartEasingAmount?: number; // amount to be eased for numbers above threshold (333)
+ separator?: string; // grouping separator (',')
+ decimal?: string; // decimal ('.')
+ // easingFn: easing function for animation (easeOutExpo)
+ easingFn?: (t: number, b: number, c: number, d: number) => number;
+ formattingFn?: (n: number) => string; // this function formats result
+ prefix?: string; // text prepended to result
+ suffix?: string; // text appended to result
+ numerals?: string[]; // numeral glyph substitution
+ enableScrollSpy?: boolean; // start animation when target is in view
+ scrollSpyDelay?: number; // delay (ms) after target comes into view
+ scrollSpyOnce?: boolean; // run only once
+ }
\ No newline at end of file
--
Gitblit v1.8.0