| | |
| | | "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", |
| | |
| | | "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", |
| | |
| | | }, |
| | | "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", |
| | |
| | | width: 100%;
|
| | | }
|
| | | #app{
|
| | |
|
| | | .content_wrap{
|
| | | color: #d3d6dd;
|
| | | }
|
| | | } |
| New file |
| | |
| | | <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>
|
| New file |
| | |
| | | import CountUp from "./count-up.vue"
|
| | | export default CountUp
|
| | |
|
| | |
| | | * @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);
|
| | |
| | | height="1080" |
| | | :delay="500" |
| | | :fullScreen="false" |
| | | :boxStyle="{ background: '#000' }" |
| | | :boxStyle="{ background: '#03050C' }" |
| | | :wrapperStyle="wrapperStyle" |
| | | > |
| | | <div class="content_wrap"> |
| | |
| | | <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>
|
| | |
|
| New file |
| | |
| | | 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
|
| | | } |