You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
4.7 KiB
197 lines
4.7 KiB
<template>
|
|
<span>
|
|
{{ displayValue }}
|
|
</span>
|
|
</template>
|
|
<script>
|
|
import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
|
|
export default {
|
|
props: {
|
|
startVal: {
|
|
type: Number,
|
|
required: false,
|
|
default: 0,
|
|
},
|
|
endVal: {
|
|
type: Number,
|
|
required: false,
|
|
default: 0,
|
|
},
|
|
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
|
|
},
|
|
},
|
|
destroyed() {
|
|
cancelAnimationFrame(this.rAF)
|
|
},
|
|
}
|
|
</script>
|
|
|