您的当前位置:首页正文

VUE3----数字增加,兼容小程序, 组件封装

2024-11-25 来源:个人技术集锦

数字增加,兼容小程序, 组件封装

<template>
	<view>{{props.prefix}}{{ displayValue }}{{props.suffix}}</view>
</template>

<script setup>
	import {
		ref,
		onMounted,
		onUnmounted
	} from 'vue';
	import {
		requestAnimationFrame,
		cancelAnimationFrame
	} from '@/utils/base/requestAnimationFrame'

	const props = defineProps({
		start: {
			type: Number,
			default: 0
		},
		end: {
			type: Number,
			required: true
		},
		duration: {
			type: Number,
			default: 2000
		},
		prefix: {
			type: String,
			default: '',
		},
		suffix: {
			type: String,
			default: '',
		},
	});

	let timer = ''
	const frame = 1000 / 60 // 16.7
	const displayValue = ref(props.start);

	const startCount = () => {
		if (timer) {
			clearInterval(timer);
		}

		let step = (props.end - props.start) / (props.duration / frame);
		step = step > 0 ? Math.ceil(step) : Math.floor(step);

		timer = setInterval(() => {
			if (displayValue.value == props.end) {
				clearInterval(timer);
			} else {
				displayValue.value += step;
				if ((step > 0 && displayValue.value > props.end) || (step < 0 && displayValue.value < props
						.end)) {
					displayValue.value = props.end;
				}
			}
		}, frame);
	}

	onMounted(() => {
		startCount();
	});

	onUnmounted(() => {
		if (timer) {
			clearInterval(timer);
		}
	});
</script>

requestAnimationFrame

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

let requestAnimationFrame
let cancelAnimationFrame

// 判断是否是服务器环境
const isServer = typeof window === 'undefined'
if (isServer) {
	requestAnimationFrame = function () {
		return
	}
	cancelAnimationFrame = function () {
		return
	}
} 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(() => {
				callback(currTime + timeToCall)
			}, timeToCall)
			lastTime = currTime + timeToCall
			return id
		}

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

export { requestAnimationFrame, cancelAnimationFrame }

效果图

显示全文