vue3+elementPlus:实现数字滚动效果(用于大屏可视化)

news/2025/4/1 3:31:35/

自行封装注册一个公共组件

案例一:

//成功案例:
//NumberScroll.vue
/*
数字滚动特效组件 NumberScroll
*/<template><span class="number-scroll-grow"><spanref="numberScroll":data-time="time"class="number-scroll":data-value="value">0</span></span>
</template><script>
import { defineComponent } from "vue";
export default defineComponent({name: "numberScroll",props: {time: {type: Number,default: 2,},value: {type: Number,default: 0,},thousandSign: {type: Boolean,default: () => false,},},data() {return {oldValue: 0,};},watch: {value: function (value, oldValue) {this.numberScroll(this.$refs.numberScroll);},},methods: {numberScroll(ele) {let _this = this;let value = _this.value - _this.oldValue;let step = (value * 10) / (_this.time * 100);let current = 0;let start = _this.oldValue;let t = setInterval(function () {start += step;if (start > _this.value) {clearInterval(t);start = _this.value;t = null;}if (current === start) {return;}current = parseInt(start);_this.oldValue = current;if (_this.thousandSign) {ele.innerHTML = current.toString().replace(/(\d)(?=(?:\d{3}[+]?)+$)/g, "$1,");} else {ele.innerHTML = current.toString();}}, 10);},},mounted() {this.$nextTick(() => {this.numberScroll(this.$refs.numberScroll);});},
});
</script><style lang="scss" scoped>
.number-scroll-grow {transform: translateZ(0);
}
</style>//单页面
//html
<div class="count"><!-- 组件 --><numberScroll :value="datalist.equip.realTimeDeviceCount" :time="30"></numberScroll>
</div>

案例二

这个是拉取vue-count-to插件源码,因为这个插件在vue3里不能用

//先在common文件夹建立requestAnimationFrame.js
let lastTime = 0
const prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀let requestAnimationFrame
let cancelAnimationFrameconst isServer = typeof window === 'undefined'
if (isServer) {requestAnimationFrame = function () {}cancelAnimationFrame = function () {}
} else {requestAnimationFrame = window.requestAnimationFramecancelAnimationFrame = window.cancelAnimationFramelet 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,则会退到setTimeoutif (!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 + timeToCallcallback(time)}, timeToCall)lastTime = currTime + timeToCallreturn id}cancelAnimationFrame = function (id) {window.clearTimeout(id)}}
}export { requestAnimationFrame, cancelAnimationFrame }//再在components文件夹建立CountTo.vue
<template><span>{{displayValue}}</span></template><script>import { requestAnimationFrame, cancelAnimationFrame } from '../common/js/requestAnimationFrame.js'export default {props: {startVal: {type: Number,required: false,default: 0},endVal: {type: Number,required: false,default: null},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.startValthis.startTime = nullthis.localDuration = this.durationthis.paused = falsethis.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 = nullthis.localDuration = +this.remainingthis.localStartVal = +this.printValrequestAnimationFrame(this.count)},reset () {this.startTime = nullcancelAnimationFrame(this.rAF)this.displayValue = this.formatNumber(this.startVal)},count (timestamp) {if (!this.startTime) this.startTime = timestampthis.timestamp = timestampconst progress = timestamp - this.startTimethis.remaining = this.localDuration - progressif (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>//最后在单文件的html里直接使用
<count-to :
startVal="0" 
:endVal="datalist.equip.realTimeDeviceCount" 
:duration="4000">
</count-to>

上一篇文章,

uniapp踩坑之项目:uni.previewImage简易版预览单图片-CSDN博客文章浏览阅读547次。uniapp踩坑之项目:uni.previewImage简易版预览单图片,主要使用uni.previewImage_uni.previewimagehttps://blog.csdn.net/weixin_43928112/article/details/136565397?spm=1001.2014.3001.5501


http://www.ppmy.cn/news/1409398.html

相关文章

【单片机】74HC4052电路图,单片机端口复用电路

74HC4052电路图 如下图&#xff0c;还是很好理解&#xff0c;PA9、PA10是单片机引脚。 当A和B是00&#xff0c;那么就是X-COM和0X短路&#xff0c;Y-COM和0Y短路。 当A和B是01&#xff0c;那么就是X-COM和1X短路&#xff0c;Y-COM和1Y短路。 以此类推。 74HC 工艺可以直接3.…

RocketMq实现单条发送,批量消费

1.传送门 安装RocketMq&#xff0c;RocketMq图形界面&#xff0c;spring boot集成RocketMq&#xff0c;参考以下三篇 本文安装版本是目前最新版RocketMq 5.2.0 安装RocketMq&#xff08;服务器Mq配置外网IP&#xff09;_rocket mq如何不使用ip连接-CSDN博客 RocketMq安装控…

python爬虫学习第十五天-------ajax的get和post请求

嗨嗨嗨&#xff01;兄弟姐妹大家好哇&#xff01;今天我们来学习ajax的get和post请求 一、了解ajax Ajax&#xff08;Asynchronous JavaScript and XML&#xff09;是一种在 Web 开发中用于创建交互式网页应用程序的技术。通过 Ajax&#xff0c;网页可以在不重新加载整个页面…

Linux 常用指令及其理论知识

个人主页&#xff1a;仍有未知等待探索-CSDN博客 专题分栏&#xff1a;http://t.csdnimg.cn/Tvyou 欢迎各位指教&#xff01;&#xff01;&#xff01; 目录 一、理论知识 二、基础指令 1、ls指令&#xff08;列出该目录下的所有子目录和文件&#xff09; 语法&#xff1a; …

俺们家Copilot和ChatGPT可不是一回事

俺们微软真的很想让大家使用俺们家的 Copilot 人工智能工具&#xff0c;不管大家是否愿意 。 一份新的报告显示&#xff0c;一些客户遇到了一个问题&#xff1a;它没有 ChatGPT 那么好用。但俺们微软认为&#xff0c;问题出在他们没能正确使用俺们家 Copilot 或不理解这两种产…

[xboard]real6410-3 S3C6410光盘资料与功能测试

文章目录 1 real6410官方资源1 官方镜像2 官方源码3 官方测试2 ok6410a资源官方镜像3 友善6410资源1 官方镜像4 友坚5 uboot学习参考1 real6410官方资源 1 官方镜像 2 官方源码 3 官方测试 2 ok6410a资源 官方镜像 http://bbs.witech.com.cn/thread-44722-1-1.h

MySQL-基本SQL语句编写:运算符练习

运算符练习 1.选择工资不在5000到12000的员工的姓名和工资 SELECT last_name,salary FROM employees #where salary not between 5000 and 12000; WHERE salary < 5000 OR salary > 12000;2.选择在20或50号部门工作的员工姓名和部门号 SELECT last_name,department_id…

Springboot 集成Rabbitmq之延时队列

1.首先确保已经引入了Spring AMQP和RabbitMQ的相关依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId> </dependency> 2. 创建一个普通队列并设置TTL&#x…