vue 数字递增 视觉数字缓慢增加(滚动从0到&)

使用

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>


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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值