mirror of
https://github.com/ialley-workshop-open/uni-halo.git
synced 2026-06-12 13:19:31 +08:00
v1.0.0-beta 源码正式开源
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
//此库移植自:https://github.com/sitonlotus/vue-digital-flop
|
||||
let lastTime = 0
|
||||
const prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀
|
||||
|
||||
let requestAnimationFrame
|
||||
let cancelAnimationFrame
|
||||
let prefix
|
||||
// #ifdef H5
|
||||
requestAnimationFrame = window.requestAnimationFrame
|
||||
cancelAnimationFrame = window.cancelAnimationFrame
|
||||
// 通过遍历各浏览器前缀,来得到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']
|
||||
}
|
||||
// #endif
|
||||
|
||||
|
||||
|
||||
// 如果当前浏览器不支持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 = setTimeout(() => {
|
||||
callback(currTime + timeToCall)
|
||||
}, timeToCall)
|
||||
lastTime = currTime + timeToCall
|
||||
return id
|
||||
}
|
||||
|
||||
cancelAnimationFrame = function(id) {
|
||||
clearTimeout(id)
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
requestAnimationFrame,
|
||||
cancelAnimationFrame
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
<template>
|
||||
<view class="tm-flop vertical-align-middle d-inline-block ">
|
||||
<slot name="default" :value="displayValue">{{ displayValue }}</slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 数字翻牌
|
||||
* @property {Number} startVal = [] 0,起始值
|
||||
* @property {Number} endVal = [] 0,最终值
|
||||
* @property {Number} duration = [] 3000,从起始值到结束值数字变动的时间
|
||||
* @property {Boolean} autoplay = [] true,是否自动播放
|
||||
* @property {Number} decimals = [] 0,保留的小数位数
|
||||
* @property {String} decimal = [] '.',小数点分割符号
|
||||
* @property {String} separator = [] ',',上了三位数分割的符号
|
||||
* @property {String} prefix = [] '',前缀
|
||||
* @property {String} suffix = [] '',后缀
|
||||
* @property {Boolean} isFrequent = [] false,是否隔一段时间数字跳动,这里的跳动是隔一段时间设置初始值
|
||||
* @property {Number} frequentTime = [] 5000,跳动间隔时间
|
||||
* 此库移植自:https://github.com/sitonlotus/vue-digital-flop
|
||||
*/
|
||||
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
|
||||
import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame';
|
||||
export default {
|
||||
name: 'tm-flop',
|
||||
components: {
|
||||
tmTranslate
|
||||
},
|
||||
props: {
|
||||
/**
|
||||
* @description 起始值
|
||||
*/
|
||||
startVal: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0
|
||||
},
|
||||
/**
|
||||
* @description 最终值
|
||||
*/
|
||||
endVal: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 2021
|
||||
},
|
||||
/**
|
||||
* @description 从起始值到结束值数字变动的时间
|
||||
*/
|
||||
duration: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 3000
|
||||
},
|
||||
/**
|
||||
* @description 是否自动播放
|
||||
*/
|
||||
autoplay: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true
|
||||
},
|
||||
/**
|
||||
* @description 保留的小数位数
|
||||
*/
|
||||
decimals: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
validator(value) {
|
||||
return value >= 0;
|
||||
}
|
||||
},
|
||||
decimal: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '.'
|
||||
},
|
||||
/**
|
||||
* @description 三位三位的隔开效果
|
||||
*/
|
||||
separator: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: ','
|
||||
},
|
||||
/**
|
||||
* @description 前缀
|
||||
* @example '¥' 人民币前缀
|
||||
*/
|
||||
prefix: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* @description 后缀
|
||||
* @example
|
||||
*/
|
||||
suffix: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: ''
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 是否具有连贯性
|
||||
*/
|
||||
useEasing: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 是否隔一段时间数字跳动,这里的跳动是隔一段时间设置初始值
|
||||
*/
|
||||
isFrequent: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
/**
|
||||
* @description 跳动间隔时间
|
||||
*/
|
||||
frequentTime: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 5000
|
||||
}
|
||||
},
|
||||
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,
|
||||
timer: 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();
|
||||
}
|
||||
if (this.isFrequent && this.frequentTime) {
|
||||
this.timer = setInterval(() => {
|
||||
this.start(this.randomNum(0, this.endVal));
|
||||
}, this.frequentTime);
|
||||
}
|
||||
this.$emit('mountedCallback');
|
||||
},
|
||||
destroy(){
|
||||
this.destroyed();
|
||||
},
|
||||
methods: {
|
||||
easingFn(t = 0, b = 0, c = 0, d = 0) {
|
||||
let p = (c * (-Math.pow(2, (-10 * t) / d) + 1) * 1024) / 1023 + b;
|
||||
return p;
|
||||
},
|
||||
randomNum(a, b) {
|
||||
return Math.round(Math.random() * (b - a) + a);
|
||||
},
|
||||
start(startVal) {
|
||||
this.localStartVal = startVal || 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) || 0;
|
||||
} 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);
|
||||
this.timer && clearInterval(this.timer);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
Reference in New Issue
Block a user