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

news2024/11/17 19:40:11

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

案例一:

//成功案例:
//NumberScroll.vue
/*
数字滚动特效组件 NumberScroll
*/

<template>
  <span class="number-scroll-grow">
    <span
      ref="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 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 }

//再在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.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>
 
 //最后在单文件的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.coloradmin.cn/o/1567766.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

intellij idea 使用git的 cherry pick 摘取其他分支的comment

cherry pick 摘取其他分支的comment 如果想把 feature_v1.0 分支的comment 摘到 feature_v1.0_new 分支上&#xff0c; 先切换到 feature_v1.0_new分支&#xff0c;这一步不能少了。然后点击 下面菜单栏的 git&#xff0c;点击Local Changes旁边的 Log&#xff0c;这时能看到…

【Java】打包:JAR、EAR、WAR

打包&#xff1a;JAR、EAR、WAR war 是一个 Web 模块&#xff0c;其中需要包括 WEB-INF&#xff0c;是可以直接运行的 WEB 模块。而 jar 一般只是包括一些 class 文件&#xff0c;在声明了 main_class 之后是可以用 java 命令运行的。 它们都是压缩的包&#xff0c;拿 Tomcat …

SpringBoot登录校验(四)过滤器Filter

JWT令牌生成后&#xff0c;客户端发的请求头中会带有JWT令牌&#xff0c;服务端需要校验每个请求的令牌&#xff0c;如果在每个controller方法中添加校验模块&#xff0c;则十分复杂且冗余&#xff0c;所以引入统一拦截模块&#xff0c;将请求拦截下来并做校验&#xff0c;这块…

配置Pod使用PersistentVolume作为存储,PV类型为 hostPath

准备开始 在节点主机上创建一个 /mnt/data 目录&#xff1a; mkdir -p /mnt/data创建一个index.html文件 echo Hello from Kubernetes storage > /mnt/data/index.html创建PV 创建一个 hostPath 类型的 PersistentVolume。 Kubernetes 支持用于在单节点集群上开发和测试的…

第19次修改了可删除可持久保存的前端html备忘录:换了一个特别的倒计时时钟

第19次修改了可删除可持久保存的前端html备忘录:换了一个特别的倒计时时钟 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><met…

数据结构记录

之前记录的数据结构笔记&#xff0c;不过图片显示不了了 数据结构与算法(C版) 1、绪论 1.1、数据结构的研究内容 一般应用步骤&#xff1a;分析问题&#xff0c;提取操作对象&#xff0c;分析操作对象之间的关系&#xff0c;建立数学模型。 1.2、基本概念和术语 数据&…

glm2大语言模型服务环境搭建

一、模型介绍 ChatGLM2-6B 是开源中英双语对话模型 ChatGLM-6B 的第二代版本&#xff0c;在保留了初代模型对话流畅、部署门槛较低等众多优秀特性的基础之上&#xff0c;ChatGLM2-6B 引入了如下新特性&#xff1a; 更强大的性能&#xff1a;基于 ChatGLM 初代模型的开发经验&…

大数据实验三-HBase编程实践

目录 一&#xff0e;实验内容 二&#xff0e;实验目的 三&#xff0e;实验过程截图及说明 1、安装HBase 2、配置伪分布式模式&#xff1a; 3、使用hbase的shell命令来操作表&#xff1a; 4、使用hbase提供的javaAPI来编程实现类似操作&#xff1a; 5、实验总结及心得体会…

『VUE』10. 事件修饰符(详细图文注释)

目录 什么是事件修饰符?vuejs 不使用修饰符 原生js实现禁用事件对象的默认事件使用事件修饰符 .prevent使用事件修饰符 .stop使用事件修饰符 .self 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 什么是事件修饰符? vue 在 Vu…

『51单片机』蜂鸣器

&#x1f6a9; WRITE IN FRONT &#x1f6a9; &#x1f50e; 介绍&#xff1a;"謓泽"正在路上朝着"攻城狮"方向"前进四" &#x1f50e;&#x1f3c5; 荣誉&#xff1a;2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2222年获评…

【研发日记】白话解读UDS协议(一)——19 04读取快照服务

文章目录 前言 19服务 04子服务 19 04协议 快照存储设计 快照发送设计 功能验证 分析和应用 总结 前言 近期在一个嵌入式软件开发项目中&#xff0c;要按照UDS标准开发相关功能&#xff0c;期间在翻阅UDS标准时&#xff0c;周围同事都说很多地方晦涩难懂。所以利用晚上…

ObjectiveC-08-OOP面向对象程序设计-类的分离与组合

本节用一简短的文章来说下是ObjectiveC中的类。类其实是OOP中的一个概念&#xff0c;概念上简单来讲类是它是一组关系密切属性的集合&#xff0c;所谓的关系就是对现实事物的抽象。 上面提到的关系包括很多种&#xff0c;比如has a&#xff0c; is a&#xff0c;has some等&…

基于Java,SSM,html,Vue在线视频播放管理系统网站设计

摘要 基于Java, SSM, HTML, Vue的在线视频播放管理系统网站设计是一个利用Spring框架、SpringMVC、MyBatis&#xff08;SSM&#xff09;和前端技术HTML与Vue.js实现的多功能Web应用。这个系统旨在为用户提供一个便捷、高效的平台来上传、管理和观看视频内容&#xff0c;同时兼…

Spring与SpringBoot的区别

Spring是一个开源的Java应用程序框架&#xff0c;旨在简化企业级Java应用程序的开发。它提供了一个轻量级的容器&#xff0c;用于管理应用程序中的各个组件&#xff08;如依赖注入、AOP等&#xff09;&#xff0c;并提供了丰富的功能和模块&#xff0c;用于处理数据库访问、事务…

enqueue:oracle锁机制

实现锁的方式就是排队咯&#xff0c;那么排队就是有enqueue这么个结构来管理 管理锁的结构叫队列&#xff0c;即enqueue 所有和enqueue相关的函数都叫KSQ-- kernal service enqueue lock是从应用层面看到的锁&#xff0c;enqueue是oracle内部管理锁的一个结构。 可以用v$lock_…

ajax教程

文章目录 一、原生ajax1、AJAX 简介2、特点1&#xff09;优点2&#xff09;缺点 二、http协议1、概念2、Cookie和Session机制1&#xff09;Cookie2&#xff09;Session3&#xff09;报文 二、请求头1、概念2、常见请求头&#xff1a;3、Content-Type 三、AJAX使用1、详细操作2、…

vue快速入门(三)差值表达式

注释很详细&#xff0c;直接上代码 上一篇 新增内容 插值表达式基本用法插值表达式常用公式 源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-wid…

显示器and拓展坞PD底层协商

简介&#xff1a; PD显示器或者PD拓展坞方案中&#xff0c;连接显示设备的Type-C端口主要运行在DRP模式&#xff0c;在此模式下可以兼容Source&#xff08;显卡&#xff09;、Sink&#xff08;信号器&#xff09;、DRP&#xff08;手机、电脑&#xff09;模式的显示设备。 Sou…

维基百科:8个提升维基百科推广效果的优化技巧-华媒舍

维基百科是全球最大的在线百科全书&#xff0c;致力于向用户提供高质量、可靠的知识内容。想要让自己的文章在维基百科中获得更多的曝光度和推广效果&#xff0c;并非易事。为此&#xff0c;我们整理了以下8个提升维基百科推广效果的优化技巧。 1. 确保内容符合要求 维基百科对…

Quiet-STaR:让语言模型在“说话”前思考

大型语言模型(llm)已经变得越来越复杂&#xff0c;能够根据各种提示和问题生成人类质量的文本。但是他们的推理能力让仍然是个问题&#xff0c;与人类不同LLM经常在推理中涉及的隐含步骤中挣扎&#xff0c;这回导致输出可能在事实上不正确或缺乏逻辑。 考虑以下场景:正在阅读一…