前端实现数字自增动态效果

66 篇文章 9 订阅

在这里插入图片描述
如图所示,在请求到数据之后,数据会从零开始加载,这样的一个动态效果

<div class='item-wrap'>
    <div class='num'>
	     <WAutoAddNumber ref='totalRef' from='0' :to='total.num' :formatter='cutOutNum'></WAutoAddNumber>
     <span>{{ total.unit }}</span>
	 </div>
	 <div class='all-tip'>数据总量</div>
	 <img :src='require(`@/assets/img/all-data-img-1.png`)' alt=''>
 </div>
import WAutoAddNumber from '@/components/w-auto-add-num'

cutOutNum (num) {
  let changeNum = (num + '').split('.')
  let decimal = ''
  if (changeNum[1]) {
    decimal = changeNum[1].slice(0, 2) === '00' ? '' : changeNum[1].slice(1, 2) === '0' ? '.' + changeNum[1].slice(1, 2) : '.' + changeNum[1].slice(0, 2)
  }
  return changeNum[0] + decimal
}

WAutoAddNumber 文件

<template>
  <div v-if='showNum' v-text='showNum'></div>
</template>

<script>
  import { tween } from 'shifty'

  const TO_FLOAT = /^\d+(\.\d+)?$/
  const TO_INT = /^\[1-9][0-9]*$/
  const isNumber = (value) => {
    return typeof value === 'number' || (
      typeof value === 'string' && (TO_FLOAT.test(value) || TO_INT.test(value))
    )
  }

  export default {
    name: 'WAutoAddNumber',
    props: {
      from: {
        type: [Number, String],
        required: true,
        validator: isNumber
      },
      to: {
        type: [Number, String],
        required: true,
        validator: isNumber
      },
      duration: {
        type: [Number, String],
        default: 2000,
        validator: isNumber
      },
      // shifty中用来计算点的宽松曲线
      easing: {
        type: String,
        default: 'easeOutQuad'
      },
      formatter: {
        type: Function,
        default: parseInt
      },
      // auto:会自动新增,touch: 需要通过触发start()方法使得数字有自增的效果
      model: {
        type: String,
        validator: (value) => {
          return value === 'auto' || value === 'touch'
        },
        default: 'auto'
      },
    },
    computed: {
      __from: function () {
        return this.from
      },
      __to: function () {
        return this.to
      }
    },
    watch: {
      // 有点小问题,后面需要修改
      __to: {
        handler (newVal) {
          this.resetOptions('to', newVal)
          if (this.model === 'auto') {
            this.state = 'end'
            this.start()
          }
        }
      },
      __from: {
        handler (newVal) {
          this.resetOptions('from', newVal)
          if (this.model === 'auto') {
            this.state = 'end'
            this.start()
          }
        }
      },

    },
    data () {
      return {
        showNum: null,
        state: 'end',
        tweenOptions: {}
      }
    },
    mounted () {
      this.setTweenOptions()
      if (this.model === 'auto') this.start()
      if (this.model === 'touch') {
        typeof this.__from === 'string'
          ? this.showNum = this.formatter(parseFloat(this.__from))
          : this.showNum = this.formatter(this.__from)
      }
    },

    methods: {
      // 设置传递给tween的值的方法
      setTweenOptions () {
        let from = typeof this.__from === 'string'
          ? { x: parseFloat(this.__from) }
          : { x: this.__from }
        let to = typeof this.__to === 'string'
          ? { x: parseFloat(this.__to) }
          : { x: this.__to }
        let duration = typeof this.duration === 'string'
          ? parseFloat(this.duration)
          : this.duration

        this.tweenOptions = {
          from: from,
          to: to,
          duration: duration,
          easing: this.easing,
          step: this.updateNumber
        }
      },
      // 通过shifty来实现数字在一定时间内,从from值到to值的自增效果
      start (options) {
        if (this.state === 'start') return
        this.state = 'start'

        if (options) this.updateAttribute(this.tweenOptions, options)
        if (this.tweenOptions.duration === 0) this.tweenOptions.duration = 1

        tween(this.tweenOptions).then(this.updateNumber).then(() => {
          this.state = 'end'
        })
      },
      updateNumber (state) {
        this.showNum = this.formatter
          ? state.state
            ? this.formatter(state.state.x)
            : this.formatter(state.x)
          : state.state
            ? state.state.x
            : state.x
      },
      updateAttribute (oldObject, newObject) {
        for (let key in newObject) {
          oldObject[key] = newObject[key]
        }
      },
      resetOptions (attr, num) {
        this.tweenOptions[attr] = typeof num === 'string'
          ? { x: parseFloat(num) }
          : { x: num }
      }
    }
  }
</script>

<style lang='less' scoped>

</style>
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老电影故事

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值