使用

html
<Incremental :startVal="0" :endVal="1000" :duration="500" />

js:
import Incremental from '@/utils/num/numView'```

js

let lastTime = 0
const prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀

let requestAnimationFrame
let cancelAnimationFrame

const isServer = typeof window === 'undefined'
if (isServer) {
    requestAnimationFrame = function () {
    }
    cancelAnimationFrame = function () {
    }
} else {
    requestAnimationFrame = window.requestAnimationFrame
    cancelAnimationFrame = window.cancelAnimationFrame
    let prefix
    // 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式
    for (let i = 0; i < prefixes.length; i++) {
        if (requestAnimationFrame && cancelAnimationFrame) { break }
        prefix = prefixes[i]
        requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
        cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']
    }

    // 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
    if (!requestAnimationFrame || !cancelAnimationFrame) {
        requestAnimationFrame = function (callback) {
            const currTime = new Date().getTime()
            // 为了使setTimteout的尽可能的接近每秒60帧的效果
            const timeToCall = Math.max(0, 16 - (currTime - lastTime))
            const id = window.setTimeout(() => {
                const time = currTime + timeToCall
                callback(time)
            }, timeToCall)
            lastTime = currTime + timeToCall
            return id
        }

        cancelAnimationFrame = function (id) {
            window.clearTimeout(id)
        }
    }
}

export { requestAnimationFrame, cancelAnimationFrame }


封装vue模块 (需要时倒入)

<template>
    <span>
        {{ displayValue }}
    </span>
</template>
<script>
import { requestAnimationFrame, cancelAnimationFrame } from './num.js'
export default {
    props: {
        startVal: {
            type: Number,
            required: false,
            default: 0
        },
        endVal: {
            type: Number,
            required: false,
            default: 2017
        },
        duration: {
            type: Number,
            required: false,
            default: 3000
        },
        autoplay: {
            type: Boolean,
            required: false,
            default: true
        },
        decimals: {
            type: Number,
            required: false,
            default: 0,
            validator(value) {
                return value >= 0
            }
        },
        decimal: {
            type: String,
            required: false,
            default: '.'
        },
        separator: {
            type: String,
            required: false,
            default: ','
        },
        prefix: {
            type: String,
            required: false,
            default: ''
        },
        suffix: {
            type: String,
            required: false,
            default: ''
        },
        useEasing: {
            type: Boolean,
            required: false,
            default: true
        },
        easingFn: {
            type: Function,
            default(t, b, c, d) {
                return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b
            }
        }
    },
    data() {
        return {
            localStartVal: this.startVal,
            displayValue: this.formatNumber(this.startVal),
            printVal: null,
            paused: false,
            localDuration: this.duration,
            startTime: null,
            timestamp: null,
            remaining: null,
            rAF: null
        }
    },
    computed: {
        countDown() {
            return this.startVal > this.endVal
        }
    },
    watch: {
        startVal() {
            if (this.autoplay) {
                this.start()
            }
        },
        endVal() {
            if (this.autoplay) {
                this.start()
            }
        }
    },
    mounted() {
        if (this.autoplay) {
            this.start()
        }
        this.$emit('mountedCallback')
    },
    methods: {
        start() {
            this.localStartVal = this.startVal
            this.startTime = null
            this.localDuration = this.duration
            this.paused = false
            this.rAF = requestAnimationFrame(this.count)
        },
        pauseResume() {
            if (this.paused) {
                this.resume()
                this.paused = false
            } else {
                this.pause()
                this.paused = true
            }
        },
        pause() {
            cancelAnimationFrame(this.rAF)
        },
        resume() {
            this.startTime = null
            this.localDuration = +this.remaining
            this.localStartVal = +this.printVal
            requestAnimationFrame(this.count)
        },
        reset() {
            this.startTime = null
            cancelAnimationFrame(this.rAF)
            this.displayValue = this.formatNumber(this.startVal)
        },
        count(timestamp) {
            if (!this.startTime) this.startTime = timestamp
            this.timestamp = timestamp
            const progress = timestamp - this.startTime
            this.remaining = this.localDuration - progress

            if (this.useEasing) {
                if (this.countDown) {
                    this.printVal = this.localStartVal - this.easingFn(progress, 0, this.localStartVal - this.endVal, this.localDuration)
                } else {
                    this.printVal = this.easingFn(progress, this.localStartVal, this.endVal - this.localStartVal, this.localDuration)
                }
            } else {
                if (this.countDown) {
                    this.printVal = this.localStartVal - ((this.localStartVal - this.endVal) * (progress / this.localDuration))
                } else {
                    this.printVal = this.localStartVal + (this.endVal - this.localStartVal) * (progress / this.localDuration)
                }
            }
            if (this.countDown) {
                this.printVal = this.printVal < this.endVal ? this.endVal : this.printVal
            } else {
                this.printVal = this.printVal > this.endVal ? this.endVal : this.printVal
            }

            this.displayValue = this.formatNumber(this.printVal)
            if (progress < this.localDuration) {
                this.rAF = requestAnimationFrame(this.count)
            } else {
                this.$emit('callback')
            }
        },
        isNumber(val) {
            return !isNaN(parseFloat(val))
        },
        formatNumber(num) {
            num = num.toFixed(this.decimals)
            num += ''
            const x = num.split('.')
            let x1 = x[0]
            const x2 = x.length > 1 ? this.decimal + x[1] : ''
            const rgx = /(\d+)(\d{3})/
            if (this.separator && !this.isNumber(this.separator)) {
                while (rgx.test(x1)) {
                    x1 = x1.replace(rgx, '$1' + this.separator + '$2')
                }
            }
            return this.prefix + x1 + x2 + this.suffix
        }
    },
    unmounted() {
        cancelAnimationFrame(this.rAF)
    }
}
</script>


在这里插入图片描述
在这里插入图片描述

GitHub 加速计划 / vu / vue
108
18
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:2 个月前 )
9e887079 [skip ci] 1 年前
73486cb5 * chore: fix link broken Signed-off-by: snoppy <michaleli@foxmail.com> * Update packages/template-compiler/README.md [skip ci] --------- Signed-off-by: snoppy <michaleli@foxmail.com> Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 1 年前
Logo

新一代开源开发者平台 GitCode,通过集成代码托管服务、代码仓库以及可信赖的开源组件库,让开发者可以在云端进行代码托管和开发。旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐