应无所住,而生其心
排名
1
文章
860
粉丝
112
评论
163
net core webapi post传递参数
庸人 : 确实坑哈,我也是下班好了好几次,发现后台传递对象是可以的,但...
百度编辑器自定义模板
庸人 : 我建议换个编辑器,因为现在百度富文本已经停止维护了,用tinymec...
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术

vue实现数字翻牌器,数字滚动显示,数字动画显示

11497人阅读 2023/3/11 13:01 总访问:5182828 评论:0 收藏:0 手机
分类: 前端

效果如下:

封装组件

  1. <template>
  2. <div class="number-grow-warp">
  3. <span ref="numberGrow" :data-time="time" class="number-grow" :data-value="valnumber"></span>
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. // 组件名字
  9. name: 'NumberGrow',
  10. props: {
  11. time: {
  12. type: Number,
  13. default: 50
  14. },
  15. valnumber: {
  16. type: Number,
  17. default: 520
  18. },
  19. },
  20. watch: {
  21. // watch第一次绑定值的时候不会执行监听,修改数据才会触发函数。数字变化的时候就出现翻牌动画
  22. valnumber(newVal, oldVal) {
  23. // console.log(newVal)
  24. // console.log(oldVal)
  25. // 计算差值。不同的差值可以让间隔时间不一致
  26. let shortValue = (newVal-oldVal)
  27. let jumpTime = 145
  28. // 如果改变的数字大于30了,我们就把总时间控制到750毫秒。那么每步走的时间就是720/步数
  29. if(shortValue>30)
  30. {
  31. jumpTime = 750/shortValue
  32. }
  33. // 如果改变的数字在20到30范围内,我们就把总时间控制到750毫秒
  34. else if(shortValue>=20&&shortValue<=30)
  35. {
  36. jumpTime = 700/shortValue
  37. }
  38. // 如果改变的数字在10到20范围内,我们就把总时间控制到600毫秒
  39. else if(shortValue>=10&&shortValue<20)
  40. {
  41. jumpTime = 600/shortValue
  42. }
  43. else if(shortValue>=5&&shortValue<10)
  44. {
  45. jumpTime = 500/shortValue
  46. }
  47. else
  48. {
  49. jumpTime=145
  50. }
  51. this.numberGrow(this.$refs.numberGrow,oldVal,jumpTime)
  52. }
  53. },
  54. methods: {
  55. numberGrow(ele,oldVal,jumpTime) {
  56. let _this = this
  57. // let step = (_this.valnumber * 10) / (_this.time * 1000)
  58. // // 步长可能是小数,需要处理一下,至少不能是小数,不然效果比较差
  59. // if (step < 1) {
  60. // alert("步长小于1了")
  61. // step = 1
  62. // }
  63. //步长就设置成1吧
  64. let step= 1
  65. // let current = 0
  66. // let start = 0
  67. // 不应该从0开始应该从上一次的值开始
  68. let current = oldVal
  69. let start = oldVal
  70. let t = setInterval(function () {
  71. start += step
  72. if (start > _this.valnumber) {
  73. clearInterval(t)
  74. start = _this.valnumber
  75. t = null
  76. }
  77. if (current === start) {
  78. return
  79. }
  80. //console.log(start)
  81. current = start
  82. ele.innerHTML = current
  83. // 格式化一下计数法,三位加一个逗号分隔
  84. // ele.innerHTML = current.toString().replace(/(\d)(?=(?:\d{3}[+]?)+$)/g, '$1,')
  85. }, jumpTime)
  86. }
  87. },
  88. mounted() {
  89. // this.numberGrow(this.$refs.numberGrow)
  90. this.$refs.numberGrow.innerHTML = this.valnumber
  91. }
  92. }
  93. </script>
  94. <style>
  95. .number-grow-warp {
  96. transform: translateZ(0);
  97. }
  98. .number-grow {
  99. font-family: Arial-BoldMT;
  100. font-size: 30px;
  101. color: #ffaf00;
  102. letter-spacing: 2.67px;
  103. margin: 110px 0 20px;
  104. display: block;
  105. line-height: 64px;
  106. }
  107. </style>

上面那个没有实现数字变小的动画,需要写一下判断,每次递减就行了

  1. <template>
  2. <div class="number-grow-warp">
  3. <span ref="numberGrow" :data-time="time" class="number-grow" :data-value="valnumber"></span>
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. // 组件名字
  9. name: 'NumberGrow',
  10. props: {
  11. time: {
  12. type: Number,
  13. default: 50
  14. },
  15. valnumber: {
  16. type: Number,
  17. default: 720000
  18. },
  19. },
  20. watch: {
  21. // watch第一次绑定值的时候不会执行监听,修改数据才会触发函数。数字变化的时候就出现翻盘动画
  22. valnumber(newVal, oldVal) {
  23. // console.log(newVal)
  24. // console.log(oldVal)
  25. // 计算差值。不同的差值可以让间隔时间不一致
  26. let shortValue = (newVal - oldVal)
  27. // 默认是加法
  28. let changeType = "add"
  29. if (shortValue < 0) {
  30. shortValue = -(shortValue)
  31. // 如果变化是负数就变成减法
  32. changeType = "subtraction"
  33. }
  34. let jumpTime = 145
  35. // 如果改变的数字大于30了,我们就把总时间控制到750毫秒。那么每步走的时间就是720/步数
  36. if (shortValue > 30) {
  37. jumpTime = 750 / shortValue
  38. }
  39. // 如果改变的数字在20到30范围内,我们就把总时间控制到750毫秒
  40. else if (shortValue >= 20 && shortValue <= 30) {
  41. jumpTime = 700 / shortValue
  42. }
  43. // 如果改变的数字在10到20范围内,我们就把总时间控制到600毫秒
  44. else if (shortValue >= 10 && shortValue < 20) {
  45. jumpTime = 600 / shortValue
  46. }
  47. else if (shortValue >= 5 && shortValue < 10) {
  48. jumpTime = 500 / shortValue
  49. }
  50. else {
  51. jumpTime = 145
  52. }
  53. if (changeType === "add") {
  54. this.numberGrow(this.$refs.numberGrow, oldVal, jumpTime)
  55. }
  56. else {
  57. this.numberReduce(this.$refs.numberGrow, oldVal, jumpTime)
  58. }
  59. }
  60. },
  61. methods: {
  62. //数字变大
  63. numberGrow(ele, oldVal, jumpTime, changeType) {
  64. let _this = this
  65. // let step = (_this.valnumber * 10) / (_this.time * 1000)
  66. // // 步长可能是小数,需要处理一下,至少不能是小数,不然效果比较差
  67. // if (step < 1) {
  68. // alert("步长小于1了")
  69. // step = 1
  70. // }
  71. //步长就设置成1吧
  72. let step = 1
  73. if (changeType === "subtraction") {
  74. step = -1
  75. }
  76. // let current = 0
  77. // let start = 0
  78. // 不应该从0开始应该从上一次的值开始
  79. let current = oldVal
  80. let start = oldVal
  81. let t = setInterval(function () {
  82. start += step
  83. if (start > _this.valnumber) {
  84. clearInterval(t)
  85. start = _this.valnumber
  86. t = null
  87. }
  88. if (current === start) {
  89. return
  90. }
  91. //console.log(start)
  92. current = start
  93. ele.innerHTML = current
  94. // 格式化一下计数法,三位加一个逗号分隔
  95. // ele.innerHTML = current.toString().replace(/(\d)(?=(?:\d{3}[+]?)+$)/g, '$1,')
  96. }, jumpTime)
  97. },
  98. //数字变小
  99. numberReduce(ele, oldVal, jumpTime) {
  100. let _this = this
  101. let step = -1
  102. let current = oldVal
  103. let start = oldVal
  104. let t = setInterval(function () {
  105. start += step
  106. if (start <= _this.valnumber) {
  107. clearInterval(t)
  108. start = _this.valnumber
  109. t = null
  110. }
  111. if (current === start) {
  112. return
  113. }
  114. current = start
  115. ele.innerHTML = current
  116. }, jumpTime)
  117. },
  118. },
  119. mounted() {
  120. // this.numberGrow(this.$refs.numberGrow)
  121. this.$refs.numberGrow.innerHTML = this.valnumber
  122. }
  123. }
  124. </script>
  125. <style>
  126. .number-grow-warp {
  127. transform: translateZ(0);
  128. }
  129. .number-grow {
  130. font-family: Arial-BoldMT;
  131. font-size: 30px;
  132. color: #23FFFC;
  133. /* letter-spacing: 2.67px; */
  134. /* margin: 110px 0 20px; */
  135. display: block;
  136. height: 60px;
  137. line-height: 60px;
  138. }
  139. </style>

优化数字变化大导致比较久才能显示完的问题

如果数字变化大,时间间隔太短了,在那个间隔时间不一定走得完,所以时间间隔太小了,每次得步长就不能是1了,要加大一点,比如数字从0变化到37362,每次+1的时间要0.02毫秒才能到750毫秒之内走完,但是0.02毫秒是无法进行一次+1显示的,普通计算机显示器在进行一次切换显示的时间是远大于0.02毫秒的。
所以我们可以把时间和每次变化的数字同步扩大就行。比如0.02毫秒每次+1,同步扩大50倍,就变成了,1毫秒每次+50,这样还是可以保存在总时间不变的情况下,数字增加完成,只是每步数字变化变大了些,当然对应的时间间隔变大了。

  1. <template>
  2. <div class="number-grow-warp">
  3. <span ref="numberGrow" :data-time="time" class="number-grow" :data-value="valnumber"></span>
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. // 组件名字
  9. name: 'NumberGrow',
  10. props: {
  11. time: {
  12. type: Number,
  13. default: 50
  14. },
  15. valnumber: {
  16. type: Number,
  17. default: 0
  18. },
  19. },
  20. watch: {
  21. // watch第一次绑定值的时候不会执行监听,修改数据才会触发函数。数字变化的时候就出现翻牌动画
  22. valnumber(newVal, oldVal) {
  23. // console.log(newVal)
  24. // console.log(oldVal)
  25. // 计算差值。不同的差值可以让间隔时间不一致
  26. let shortValue = (newVal - oldVal)
  27. // console.log("...............数字差值.................")
  28. // console.log(shortValue)
  29. // 默认是加法
  30. let changeType = "add"
  31. if (shortValue < 0) {
  32. shortValue = -(shortValue)
  33. // 如果变化是负数就变成减法
  34. changeType = "subtraction"
  35. }
  36. let jumpTime = 145
  37. let jumpNumber =1
  38. if (shortValue > 750)
  39. {
  40. /*
  41. 时间间隔太短了,在那个间隔时间不一定走得完,所以时间间隔太小了,每次得步长就不能是1了,要加大一点,
  42. 比如数字从0变化到37362,每次+1的时间要0.02毫秒才能到720毫秒之内走完,但是0.02毫秒是无法进行一次+1显示的,普通计算机显示器在进行一次切换显示的时间是大于0.02毫秒的
  43. 所以我们可以把时间和每次变化的数字同步扩大就行。比如0.02毫秒每次+1,同步扩大50倍,就变成了,1毫秒每次+50,
  44. 这样还是可以保存在总时间不变的情况下,数字增加完成,只是每步数字变化变大了些,当然对应的时间间隔变大了。
  45. */
  46. jumpTime = 750 / shortValue
  47. // 扩大的倍数就安装750的倍数来吧,我们差不多控制到1毫秒进行一次数字改变
  48. let n = Math.round(shortValue/750)
  49. console.log("每次间隔应该扩大:"+n+"倍")
  50. // 进行一次数字改变的数值扩大n倍
  51. jumpNumber = jumpNumber*n
  52. // 时间间隔也同步扩大n倍
  53. jumpTime = jumpTime*n
  54. }
  55. // 如果改变的数字大于30了,我们就把总时间控制到750毫秒。那么每步走的时间就是720/步数
  56. else if (shortValue > 30) {
  57. jumpTime = 750 / shortValue
  58. // console.log(".....每步的时间....")
  59. // console.log(jumpTime)
  60. }
  61. // 如果改变的数字在20到30范围内,我们就把总时间控制到750毫秒
  62. else if (shortValue >= 20 && shortValue <= 30) {
  63. jumpTime = 700 / shortValue
  64. }
  65. // 如果改变的数字在10到20范围内,我们就把总时间控制到600毫秒
  66. else if (shortValue >= 10 && shortValue < 20) {
  67. jumpTime = 600 / shortValue
  68. }
  69. else if (shortValue >= 5 && shortValue < 10) {
  70. jumpTime = 500 / shortValue
  71. }
  72. else {
  73. jumpTime = 145
  74. }
  75. if (changeType === "add") {
  76. this.numberGrow(this.$refs.numberGrow, oldVal, jumpTime,jumpNumber)
  77. }
  78. else {
  79. this.numberReduce(this.$refs.numberGrow, oldVal, jumpTime,jumpNumber)
  80. }
  81. }
  82. },
  83. methods: {
  84. //数字变大
  85. numberGrow(ele, oldVal, jumpTime, jumpNumber) {
  86. let _this = this
  87. // let step = (_this.valnumber * 10) / (_this.time * 1000)
  88. // // 步长可能是小数,需要处理一下,至少不能是小数,不然效果比较差
  89. // if (step < 1) {
  90. // alert("步长小于1了")
  91. // step = 1
  92. // }
  93. //步长就设置成1吧
  94. // let step = 1
  95. let step = jumpNumber
  96. // if (changeType === "subtraction") {
  97. // step = -1
  98. // }
  99. // let current = 0
  100. // let start = 0
  101. // 不应该从0开始应该从上一次的值开始
  102. let current = oldVal
  103. let start = oldVal
  104. let t = setInterval(function () {
  105. start += step
  106. if (start > _this.valnumber) {
  107. clearInterval(t)
  108. start = _this.valnumber
  109. t = null
  110. }
  111. if (current === start) {
  112. return
  113. }
  114. //console.log(start)
  115. current = start
  116. ele.innerHTML = current
  117. // 格式化一下计数法,三位加一个逗号分隔。千分号
  118. //ele.innerHTML = current.toString().replace(/(\d)(?=(?:\d{3}[+]?)+$)/g, '$1,')
  119. }, jumpTime)
  120. },
  121. //数字变小
  122. numberReduce(ele, oldVal, jumpTime,jumpNumber) {
  123. let _this = this
  124. // let step = -1
  125. // 取负数
  126. let step = 0-jumpNumber
  127. let current = oldVal
  128. let start = oldVal
  129. let t = setInterval(function () {
  130. start += step
  131. if (start <= _this.valnumber) {
  132. clearInterval(t)
  133. start = _this.valnumber
  134. t = null
  135. }
  136. if (current === start) {
  137. return
  138. }
  139. current = start
  140. ele.innerHTML = current
  141. }, jumpTime)
  142. },
  143. },
  144. mounted() {
  145. // this.numberGrow(this.$refs.numberGrow)
  146. this.$refs.numberGrow.innerHTML = this.valnumber
  147. }
  148. }
  149. </script>
  150. <style>
  151. .number-grow-warp {
  152. transform: translateZ(0);
  153. }
  154. .number-grow {
  155. font-family: Arial-BoldMT;
  156. font-size: 29px;
  157. color: #23FFFC;
  158. /* letter-spacing: 2.67px; */
  159. /* margin: 110px 0 20px; */
  160. display: block;
  161. height: 60px;
  162. line-height: 60px;
  163. }
  164. </style>

还需要继续完善,比如字体,字号,风格等这些作为参数会更通用,还有逻辑也是现在还是写得很粗糙

优化在短时间内多次改变造成的显示问题

比如前面变化还没有完成,数字马上又变成了就会有问题,比如先从0到5,然后0到5还没有改变完成在变化到500,然后马上又变化到1000。这样的话其实有三个定时器在改变数字,第一次是从0?5,然后就是从5?500,在就是从500?1000。我们看数字变化的效果是这样的,先慢慢一个数字一个数字的再走,然后很快的加速到500,然后又数字减少到几十然后加速到1000然后又减少到几十多一点,又开始慢慢走。感觉每次变化的新的数字都不是前面赋值的而是最新赋值的一次,果然是我封装的时候只传递了旧值,根本没有传递新的值

看一下新的值是直接取的绑定的那个值,这肯定不行撒,如果多次都在运行中,就会出现刚刚运行的情况,每次都要变化的最新的值去

如果以很慢的速度变化到很大的值去就会很有问题了,数字大了走几个小时都有可能,所以每次改变的数字应该只影响本次的,新值也需要改成进行传递的方式

贴一下代码
这里还实现了一下是否使用默认样式的配置

  1. <template>
  2. <div class="number-grow-warp">
  3. <!-- <span ref="numberGrow" :data-time="time" class="number-grow" :data-value="valnumber"></span> -->
  4. <!-- 样式变成可以绑定的,引用组件的时候可以不要这个样式 -->
  5. <span ref="numberGrow" :data-time="time" :class="defaultClass" :data-value="valnumber"></span>
  6. </div>
  7. </template>
  8. <script>
  9. export default {
  10. // 组件名字
  11. name: 'NumberGrow',
  12. props: {
  13. time: {
  14. type: Number,
  15. default: 50
  16. },
  17. valnumber: {
  18. type: Number,
  19. default: 0
  20. },
  21. // 默认样式。组件内容提供了一套默认样式,如果引用组件的时候不想使用这个样式就可以修改这个参数
  22. defaultClass: {
  23. type: String,
  24. default: 'number-grow'
  25. }
  26. },
  27. data() {
  28. return {
  29. // 上次的数字变化是否已经完成,比如第一次从0到500都还没有变化完成,又要变成1000,这种就应该等待第一次运行完成后才去执行第二次的变成
  30. isLastStop: true,
  31. }
  32. },
  33. watch: {
  34. // watch第一次绑定值的时候不会执行监听,修改数据才会触发函数。数字变化的时候就出现翻牌动画
  35. valnumber(newVal, oldVal) {
  36. // console.log(newVal)
  37. // console.log(oldVal)
  38. // 判断是否上次已经改变完成了
  39. // if (this.isLastStop === true) {
  40. //console.log("上一次运行完成了"+newVal+","+oldVal)
  41. this.isLastStop = false
  42. // 计算差值。不同的差值可以让间隔时间不一致
  43. let shortValue = (newVal - oldVal)
  44. // console.log("...............数字差值.................")
  45. // console.log(shortValue)
  46. // 默认是加法
  47. let changeType = "add"
  48. if (shortValue < 0) {
  49. shortValue = -(shortValue)
  50. // 如果变化是负数就变成减法
  51. changeType = "subtraction"
  52. }
  53. let jumpTime = 145
  54. let jumpNumber = 1
  55. if (shortValue > 750) {
  56. /*
  57. 时间间隔太短了,在那个间隔时间不一定走得完,所以时间间隔太小了,每次得步长就不能是1了,要加大一点,
  58. 比如数字从0变化到37362,每次+1的时间要0.02毫秒才能到720毫秒之内走完,但是0.02毫秒是无法进行一次+1显示的,普通计算机显示器在进行一次切换显示的时间是大于0.02毫秒的
  59. 所以我们可以把时间和每次变化的数字同步扩大就行。比如0.02毫秒每次+1,同步扩大50倍,就变成了,1毫秒每次+50,
  60. 这样还是可以保存在总时间不变的情况下,数字增加完成,只是每步数字变化变大了些,当然对应的时间间隔变大了。
  61. */
  62. jumpTime = 750 / shortValue
  63. // 扩大的倍数就安装750的倍数来吧,我们差不多控制到1毫秒进行一次数字改变
  64. let n = Math.round(shortValue / 750)
  65. //console.log("每次间隔应该扩大:"+n+"倍")
  66. // 进行一次数字改变的数值扩大n倍
  67. jumpNumber = jumpNumber * n
  68. // 时间间隔也同步扩大n倍
  69. jumpTime = jumpTime * n
  70. }
  71. // 如果改变的数字大于30了,我们就把总时间控制到750毫秒。那么每步走的时间就是750/步数
  72. else if (shortValue > 30) {
  73. jumpTime = 750 / shortValue
  74. }
  75. // 如果改变的数字在20到30范围内,我们就把总时间控制到750毫秒
  76. else if (shortValue >= 20 && shortValue <= 30) {
  77. jumpTime = 700 / shortValue
  78. }
  79. // 如果改变的数字在10到20范围内,我们就把总时间控制到600毫秒
  80. else if (shortValue >= 10 && shortValue < 20) {
  81. jumpTime = 600 / shortValue
  82. }
  83. // 如果改变的数字在3到10范围内,我们就把总时间控制到530毫秒
  84. else if (shortValue >= 2 && shortValue < 10) {
  85. jumpTime = 530 / shortValue
  86. }
  87. else {
  88. //jumpTime = 145
  89. // 修改大一点吧,变化效果明显点,不然变化少了,看着一点都不明显
  90. jumpTime = 266
  91. }
  92. if (changeType === "add") {
  93. this.numberGrow(this.$refs.numberGrow, oldVal, jumpTime, jumpNumber, newVal)
  94. }
  95. else {
  96. this.numberReduce(this.$refs.numberGrow, oldVal, jumpTime, jumpNumber, newVal)
  97. }
  98. // }
  99. // else
  100. // {
  101. // console.log("上一次还没有运行完成"+newVal+","+oldVal)
  102. // }
  103. }
  104. },
  105. methods: {
  106. //数字变大
  107. numberGrow(ele, oldVal, jumpTime, jumpNumber, newVal) {
  108. let _this = this
  109. //步长就设置成1吧
  110. // let step = 1
  111. let step = jumpNumber
  112. // 不应该从0开始应该从上一次的值开始
  113. let current = oldVal
  114. let start = oldVal
  115. // 试试先清除一下上次还没有执行完的定时器了
  116. // clearInterval(t)
  117. let t = setInterval(function () {
  118. start += step
  119. if (start > newVal) {
  120. clearInterval(t)
  121. start = newVal
  122. t = null
  123. _this.isLastStop = true
  124. }
  125. if (current === start) {
  126. return
  127. }
  128. //console.log(start)
  129. current = start
  130. ele.innerHTML = current
  131. // 格式化一下计数法,三位加一个逗号分隔。千分号
  132. //ele.innerHTML = current.toString().replace(/(\d)(?=(?:\d{3}[+]?)+$)/g, '$1,')
  133. }, jumpTime)
  134. },
  135. //数字变小
  136. numberReduce(ele, oldVal, jumpTime, jumpNumber, newVal) {
  137. let _this = this
  138. // let step = -1
  139. // 取负数
  140. let step = 0 - jumpNumber
  141. let current = oldVal
  142. let start = oldVal
  143. // 试试先清除一下上次还没有执行完的定时器了
  144. // clearInterval(t)
  145. let t = setInterval(function () {
  146. start += step
  147. if (start <= newVal) {
  148. clearInterval(t)
  149. start = newVal
  150. t = null
  151. _this.isLastStop = true
  152. }
  153. if (current === start) {
  154. return
  155. }
  156. current = start
  157. ele.innerHTML = current
  158. }, jumpTime)
  159. },
  160. },
  161. mounted() {
  162. // this.numberGrow(this.$refs.numberGrow)
  163. this.$refs.numberGrow.innerHTML = this.valnumber
  164. }
  165. }
  166. </script>
  167. <style scoped>
  168. .number-grow-warp {
  169. transform: translateZ(0);
  170. }
  171. .number-grow {
  172. font-family: Arial-BoldMT;
  173. font-size: 29px;
  174. color: #23FFFC;
  175. display: block;
  176. height: 60px;
  177. line-height: 60px;
  178. }
  179. </style>

但是要注意一下会不会出现这种情况就是三次改变,照理说应该是最后一次最后完成,数字也是最后的值,但是前面的由于执行慢,反而变成了最后执行完成了,那么最后剩下的值就会有问题了,其实只要保证数字变化小的执行时机小于数字变化大的就行了,而且两次改变数字之间也是存在时间差的,所以保证这两点就不会出现上面说的情况。

继续优化可以在多个改变同时进行的时候,变成只有一个定时器在运行,停掉上一次的

比如第二个在进行改变的时候发现上一次的定时器还没有执行完成就直接停掉上一次的,马上开始这一次的改变,保证每次只有一个定时任务在执行,就不会出现那种几个定时器同时在执行,数字一会变大又变小然后在变大的情况了,这样情况的显示看起来就不是太舒服了,虽然不影响最后数字的正确性。

先定义一个变量记录一下定时器:

然后涉及到定时器的地方都换成这个变量:

然后在数字改变的时候判断一下,上一次是否执行完成,如果这一次要开始执行了,上一次的还没有执行完成的话,直接把上一次执行中的定时器干掉就行了,直接开始这一次的变化就行了

因为其实每次都是从一个数字变成需要的新数字,那么肯定是以最新的为准就行了,那么既然新的一次都开始了前面的在继续去执行就没有意义了,还会很影响美观,所以如果上一次还没有执行完毕直接干掉即可

贴一下代码:

  1. <template>
  2. <div class="number-grow-warp">
  3. <!-- <span ref="numberGrow" :data-time="time" class="number-grow" :data-value="valnumber"></span> -->
  4. <!-- 样式变成可以绑定的,引用组件的时候可以不要这个样式 -->
  5. <span ref="numberGrow" :data-time="time" :class="defaultClass" :data-value="valnumber"></span>
  6. </div>
  7. </template>
  8. <script>
  9. export default {
  10. // 组件名字
  11. name: 'NumberGrow',
  12. props: {
  13. time: {
  14. type: Number,
  15. default: 50
  16. },
  17. valnumber: {
  18. type: Number,
  19. default: 0
  20. },
  21. // 默认样式。组件内容提供了一套默认样式,如果引用组件的时候不想使用这个样式就可以修改这个参数
  22. defaultClass: {
  23. type: String,
  24. default: 'number-grow'
  25. }
  26. },
  27. data() {
  28. return {
  29. // 上次的数字变化是否已经完成,比如第一次从0到500都还没有变化完成,又要变成1000,这种就应该等待第一次运行完成后才去执行第二次的变成()
  30. //isLastStop: true,
  31. // 定时器记录一下,方便判断上一次还没有运行完成的情况
  32. myInterval:null
  33. }
  34. },
  35. watch: {
  36. // watch第一次绑定值的时候不会执行监听,修改数据才会触发函数。数字变化的时候就出现翻牌动画
  37. valnumber(newVal, oldVal) {
  38. // console.log(newVal)
  39. // console.log(oldVal)
  40. // 说明上次的运行还没有执行完毕
  41. if(this.myInterval!=null)
  42. {
  43. //直接清楚掉上一次的运行
  44. clearInterval(this.myInterval)
  45. // 设置成执行完毕的效果
  46. //this.valnumber = oldVal
  47. //this.$refs.numberGrow.innerHTML = this.valnumber
  48. }
  49. // 判断是否上次已经改变完成了
  50. // if (this.isLastStop === true) {
  51. //console.log("上一次运行完成了"+newVal+","+oldVal)
  52. // this.isLastStop = false
  53. // 计算差值。不同的差值可以让间隔时间不一致
  54. let shortValue = (newVal - oldVal)
  55. // console.log("...............数字差值.................")
  56. // console.log(shortValue)
  57. // 默认是加法
  58. let changeType = "add"
  59. if (shortValue < 0) {
  60. shortValue = -(shortValue)
  61. // 如果变化是负数就变成减法
  62. changeType = "subtraction"
  63. }
  64. let jumpTime = 145
  65. let jumpNumber = 1
  66. if (shortValue > 750) {
  67. /*
  68. 时间间隔太短了,在那个间隔时间不一定走得完,所以时间间隔太小了,每次得步长就不能是1了,要加大一点,
  69. 比如数字从0变化到37362,每次+1的时间要0.02毫秒才能到720毫秒之内走完,但是0.02毫秒是无法进行一次+1显示的,普通计算机显示器在进行一次切换显示的时间是大于0.02毫秒的
  70. 所以我们可以把时间和每次变化的数字同步扩大就行。比如0.02毫秒每次+1,同步扩大50倍,就变成了,1毫秒每次+50,
  71. 这样还是可以保存在总时间不变的情况下,数字增加完成,只是每步数字变化变大了些,当然对应的时间间隔变大了。
  72. */
  73. jumpTime = 750 / shortValue
  74. // 扩大的倍数就安装750的倍数来吧,我们差不多控制到1毫秒进行一次数字改变
  75. let n = Math.round(shortValue / 750)
  76. //console.log("每次间隔应该扩大:"+n+"倍")
  77. // 进行一次数字改变的数值扩大n倍
  78. jumpNumber = jumpNumber * n
  79. // 时间间隔也同步扩大n倍
  80. jumpTime = jumpTime * n
  81. }
  82. // 如果改变的数字大于30了,我们就把总时间控制到750毫秒。那么每步走的时间就是750/步数
  83. else if (shortValue > 30) {
  84. jumpTime = 750 / shortValue
  85. }
  86. // 如果改变的数字在20到30范围内,我们就把总时间控制到750毫秒
  87. else if (shortValue >= 20 && shortValue <= 30) {
  88. jumpTime = 700 / shortValue
  89. }
  90. // 如果改变的数字在10到20范围内,我们就把总时间控制到600毫秒
  91. else if (shortValue >= 10 && shortValue < 20) {
  92. jumpTime = 600 / shortValue
  93. }
  94. // 如果改变的数字在3到10范围内,我们就把总时间控制到530毫秒
  95. else if (shortValue >= 2 && shortValue < 10) {
  96. jumpTime = 530 / shortValue
  97. }
  98. else {
  99. //jumpTime = 145
  100. // 修改大一点吧,变化效果明显点,不然变化少了,看着一点都不明显
  101. jumpTime = 266
  102. }
  103. if (changeType === "add") {
  104. this.numberGrow(this.$refs.numberGrow, oldVal, jumpTime, jumpNumber, newVal)
  105. }
  106. else {
  107. this.numberReduce(this.$refs.numberGrow, oldVal, jumpTime, jumpNumber, newVal)
  108. }
  109. // }
  110. // else
  111. // {
  112. // console.log("上一次还没有运行完成"+newVal+","+oldVal)
  113. // }
  114. }
  115. },
  116. methods: {
  117. //数字变大
  118. numberGrow(ele, oldVal, jumpTime, jumpNumber, newVal) {
  119. let _this = this
  120. // let step = (_this.valnumber * 10) / (_this.time * 1000)
  121. // // 步长可能是小数,需要处理一下,至少不能是小数,不然效果比较差
  122. // if (step < 1) {
  123. // alert("步长小于1了")
  124. // step = 1
  125. // }
  126. //步长就设置成1吧
  127. // let step = 1
  128. let step = jumpNumber
  129. // 不应该从0开始应该从上一次的值开始
  130. let current = oldVal
  131. let start = oldVal
  132. // 试试先清除一下上次还没有执行完的定时器了
  133. // clearInterval(t)
  134. _this.myInterval = setInterval(function () {
  135. start += step
  136. if (start > newVal) {
  137. clearInterval(_this.myInterval)
  138. start = newVal
  139. // t = null
  140. _this.myInterval = null
  141. // _this.isLastStop = true
  142. }
  143. if (current === start) {
  144. return
  145. }
  146. //console.log(start)
  147. current = start
  148. ele.innerHTML = current
  149. // 格式化一下计数法,三位加一个逗号分隔。千分号
  150. //ele.innerHTML = current.toString().replace(/(\d)(?=(?:\d{3}[+]?)+$)/g, '$1,')
  151. }, jumpTime)
  152. },
  153. //数字变小
  154. numberReduce(ele, oldVal, jumpTime, jumpNumber, newVal) {
  155. let _this = this
  156. // let step = -1
  157. // 取负数
  158. let step = 0 - jumpNumber
  159. let current = oldVal
  160. let start = oldVal
  161. // 试试先清除一下上次还没有执行完的定时器了
  162. // clearInterval(t)
  163. _this.myInterval = setInterval(function () {
  164. start += step
  165. if (start <= newVal) {
  166. clearInterval(_this.myInterval)
  167. start = newVal
  168. // t = null
  169. _this.myInterval = null
  170. //_this.isLastStop = true
  171. }
  172. if (current === start) {
  173. return
  174. }
  175. current = start
  176. ele.innerHTML = current
  177. }, jumpTime)
  178. },
  179. },
  180. mounted() {
  181. // this.numberGrow(this.$refs.numberGrow)
  182. this.$refs.numberGrow.innerHTML = this.valnumber
  183. }
  184. }
  185. </script>
  186. <style scoped>
  187. .number-grow-warp {
  188. transform: translateZ(0);
  189. }
  190. .number-grow {
  191. font-family: Arial-BoldMT;
  192. font-size: 29px;
  193. color: #23FFFC;
  194. /* letter-spacing: 2.67px; */
  195. /* margin: 110px 0 20px; */
  196. display: block;
  197. height: 60px;
  198. line-height: 60px;
  199. }
  200. </style>

使用组件

  1. <!-- 分析趋势 -->
  2. <template>
  3. <div>
  4. <div class="analyseTrend">
  5. <div class="analyseTrend_warp">
  6. <div class="analyseTrend_content_left">
  7. <div class="analyseTrend_content_tag">知识点数</div>
  8. <div style="display: flex;">
  9. <NumberGrow :valnumber="evalData.evalCount"></NumberGrow>
  10. <div class="analyseTrend_conten_unit"></div>
  11. </div>
  12. </div>
  13. <div class="analyseTrend_content_right">
  14. <div class="analyseTrend_content_tag">评估累计</div>
  15. <div style="display: flex;">
  16. <NumberGrow :valnumber="evalData.evalDoCount"></NumberGrow>
  17. <div class="analyseTrend_conten_unit">人次</div>
  18. </div>
  19. </div>
  20. </div>
  21. <div class="splitline"></div>
  22. <div class="analyseTrend_warp">
  23. <div class="analyseTrend_content_left">
  24. <div class="analyseTrend_content_tag">实验数</div>
  25. <div style="display: flex;">
  26. <NumberGrow :valnumber="labroomData.labroomCount"></NumberGrow>
  27. <div class="analyseTrend_conten_unit"></div>
  28. </div>
  29. </div>
  30. <div class="analyseTrend_content_right">
  31. <div class="analyseTrend_content_tag">实验累计人次</div>
  32. <div style="display: flex;">
  33. <NumberGrow :valnumber="labroomData.labroomStuCount"></NumberGrow>
  34. <div class="analyseTrend_conten_unit">人次</div>
  35. </div>
  36. </div>
  37. </div>
  38. <div class="splitline"></div>
  39. <div class="analyseTrend_warp">
  40. <div class="analyseTrend_content_left">
  41. <div class="analyseTrend_content_tag">项目数</div>
  42. <div style="display: flex;">
  43. <NumberGrow :valnumber="prodData.prodCount"></NumberGrow>
  44. <div class="analyseTrend_conten_unit"></div>
  45. </div>
  46. </div>
  47. <div class="analyseTrend_content_right">
  48. <div class="analyseTrend_content_tag">项目累计人次</div>
  49. <div style="display: flex;">
  50. <NumberGrow :valnumber="prodData.prodStuCount"></NumberGrow>
  51. <div class="analyseTrend_conten_unit">人次</div>
  52. </div>
  53. </div>
  54. </div>
  55. </div>
  56. </div>
  57. </template>
  58. <script >
  59. import NumberGrow from '@/views/component/numberGrow.vue'
  60. export default {
  61. components: {
  62. NumberGrow
  63. },
  64. // 组件名字
  65. name: 'IntegratedData',
  66. // 组件参数
  67. props: {
  68. },
  69. data() {
  70. return {
  71. evalData:{
  72. evalCount:3212,
  73. evalDoCount:1678467
  74. },
  75. labroomData:
  76. {
  77. labroomCount:5985,
  78. labroomStuCount:2897678
  79. },
  80. prodData:{
  81. prodCount:3212,
  82. prodStuCount:1678467
  83. }
  84. }
  85. },
  86. mounted() {
  87. // 模拟数据变化
  88. setInterval(() => {
  89. let becorevalprodStuCount = this.prodData.prodStuCount
  90. this.prodData.prodStuCount=becorevalprodStuCount+60
  91. let becoreval = this.prodData.prodCount
  92. this.prodData.prodCount=becoreval+100
  93. let beforeevalData = this.evalData.evalDoCount
  94. this.evalData.evalDoCount=beforeevalData+50
  95. let beforeevalDatalabroomData = this.labroomData.labroomCount
  96. this.labroomData.labroomCount=beforeevalDatalabroomData+50
  97. let labroomStuCount = this.labroomData.labroomStuCount
  98. this.labroomData.labroomStuCount=labroomStuCount+50
  99. let beforeevalDataevalCount = this.evalData.evalCount
  100. this.evalData.evalCount=beforeevalDataevalCount+70
  101. }, 2000);
  102. // setInterval(() => {
  103. // let val = this.numberData.labroom.number[0]
  104. // this.numberData.labroom.number[0] = val + 100
  105. // //相当于复制了一份新的对象在给自己
  106. // this.numberData.labroom = { ...this.numberData.labroom }
  107. // let prodval = this.numberData.prod.number[0]
  108. // this.numberData.prod.number[0] = prodval + 100
  109. // this.numberData.prod = { ...this.numberData.prod }
  110. // // console.log(val)
  111. // // console.log("------------------")
  112. // }, 1800)
  113. },
  114. beforeDestroy() {
  115. },
  116. methods: {
  117. }
  118. }
  119. </script>
  120. <style lang="scss" scoped>
  121. // 分割线渐变 两边浅中间深
  122. .splitline {
  123. height: 1px;
  124. // background: radial-gradient(#3FDDFA -54%, #fff 100%);
  125. // background:linear-gradient(to left,#fff,#3FDDFA,#fff);
  126. background: linear-gradient(to left, rgba(63, 221, 250, 0), #3FDDFA 50%, rgba(63, 221, 250, 0));
  127. // background:linear-gradient(to left,rgba(63, 221, 250, 0) 0%,#3FDDFA 50%,rgba(63, 221, 250, 0) 100%);
  128. }
  129. .analyseTrend {
  130. margin-top: 26px;
  131. // margin-left: -10px;
  132. .analyseTrend_warp {
  133. height: 136px;
  134. display: flex;
  135. align-items: center;
  136. .analyseTrend_content_left {
  137. width: 150px;
  138. }
  139. .analyseTrend_content_right {
  140. width: 160px;
  141. }
  142. .analyseTrend_content_tag {
  143. font-size: 16px
  144. }
  145. // 单位
  146. .analyseTrend_conten_unit {
  147. height: 60px;
  148. line-height: 60px;
  149. padding-top: 10px;
  150. color: #23FFFC;
  151. font-size: 15px;
  152. }
  153. }
  154. }
  155. </style>

欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739。有需要软件开发,或者学习软件技术的朋友可以和我联系~(Q:815170684)

评价

vue.js+Layer实现表格数据绑定与更新

一:使用Vue.js绑定好数据与更新事件 使用v-on绑定好事件,在事件里边直接把该行数据传递进去,在更新方法里边就可以直接...

vue.js 实现省市联动

HTML代码&lt;divid=&quot;pro_citys&quot;&gt; 省:&lt;selectid=&quot;provice&quot;v-on:change=&quot;prochange()&quo...

vue.js常见问题

一:花括号当做字符串显示的问题1:检查下绑定到vue.js的id是否重复,如果id重复了,就有可能存在这种问题,因为有可能把数...

vue.js常用指令

v-html可以把字符串当成一个html来渲染,而不是原样输出Html类似.net mvc中的@Html.Raw()方法&lt;divv-html=&quot;item.tit...

干货!div滚动到一定位置就固定他。vue中实现一侧滚动到底部就固定

尊重原创:转载请注名出处div滚动到一定位置就固定他,例如左边的内容很多,右边的内容很少,如果不处理滚动到一定位置后右...

vue.js常用指令事件绑定等vue过滤器解析状态过滤器多个参数。vue表格状态解析。vue解析类型element ui解析类型状态el-tag

按照html的编码显示:v-html&lt;div class=&quot;font_info&quot; v-html=&quot;item.Content&quot;&gt;{{item.Content}}&l...

vue.js if用法

vue.js if可以做一些判断例如我们要把下面这个输出varvm=newVue({ el:&quot;#content&quot;, data:{ titles:[&quot;小明...

vue.js 学习日记第一章-安装vue开发环境

官网:https://cn.vuejs.org/v2/guide/ 这是一篇学习性文章,不定时更新,用来记录我学习vue.js的过程。 首先,是v...

vue.js 学习日记第二章-在vue中编写function及一些简单指令

官网:https://cn.vuejs.org/v2/guide/ vue.js 学习日记第一章:http://www.tnblog.net/18323015640/article/details/2...

vue.js 学习日记第三章-vue中的简单事件及事件修饰符

官网:https://cn.vuejs.org/v2/guide/ vue.js 学习日记第二章:http://www.tnblog.net/18323015640/article/details/2...

vue.js 学习日记第四章-vue中文本框数据获取与绑定及computed计算属性

官网:https://cn.vuejs.org/v2/guide/ vue.js学习日记第三章: http://www.tnblog.net/18323015640/article/details/2...

vue.js 学习日记第五章-v-if和v-for指令的使用方式

官网:https://cn.vuejs.org/v2/guide/ vue.js学习日记第四章: http://www.tnblog.net/18323015640/article/details/2...

vue.js 学习日记第六章-vue组件初步学习

官网:https://cn.vuejs.org/v2/guide/ vue.js学习日记第五章: http://www.tnblog.net/18323015640/article/details/2...

vue.js学习日记第七章-搭建脚手架

官网:https://cn.vuejs.org/v2/guide/ vue.js学习日记第六章: http://www.tnblog.net/18323015640/article/details/2...

vue实现好友选中效果

逛过vue官网肯定会发现一个有趣的指令“v-for”,相比与以前拼接html代码确实要上档次一点,而且减少了工作量,先看一波效...

js时间格式化vue.js时间格式化带T 时间格式化

也可以借助moment库, 参考:https://www.tnblog.net/aojiancc2/article/details/8079moment库有点大,推荐可以使用day.js...