vue 数字滚动

262 阅读1分钟

image.png

<template>
    <div class="relaxRightTop">
        <!-- 标题-->
        <headerCom title="休闲渔船管理">
        </headerCom> 
        <!-- 内容 -->
        <div class="common-map-index-part-content" v-loading="isLoading"
         element-loading-text="拼命加载中"
         element-loading-background="rgba(0, 0, 0, 0.3)" style="padding: 15px">
            <div class="relaxRightTop-warp">
                <div style="width: 48%;height: 100%" v-for="(item, i) in dataList" :key=" 'dataItem' + i">
                    <div><span class="relaxRightTop-warp-fffItem">{{item.name}}</span><span class="relaxRightTop-warp-fffItemUnit">({{item.unit}})</span></div>
                    <!-- 数字滚动 -->
                    <count :count="item.value" :type="item.type" :color="item.color" style="padding-top:5px"></count>
                    <div>
                        <!-- 进度条 -->
                        <Process :value="item.rateValue"></Process>
                    </div>
                </div>

            </div>
        </div>
    </div>
</template>
<script>
import headerCom from "@/components/commomHeader/index.vue";
import count from "./components/scrollCount.vue"
import Process from "./components/rightProcess.vue"
export default {
    name: "relaxLeftTop",
    components: {
        headerCom, count, Process
    },
    data () {
        return {
            isLoading: false,
            dataList: [
                {
                    name: '今日进港',
                    unit: '艘',
                    value: 60600,
                    color: '#2cecff',
                    type: 0,
                    rateValue: {
                        name: '进港率',
                        value: '82%',
                        color: ['#19B1FB', '#2CECFF'],
                    }
                },
                {
                    name: '今日出港',
                    value: 5200,
                    unit: '艘',
                    color: '#ffc500',
                    type: 1,
                    rateValue: {
                        name: '出港率',
                        value: '65%',
                        color: ['#ff7e00', '#ffc500']
                    }
                },
            ],
        }
    },
    mounted () {

    },
    methods: {
        // 更多
        handleMore () {

        }
    }
}
</script>
<style lang="scss" scoped>
.relaxRightTop{
    &-warp{
        width: 100%;
        height: 100%;
        display: flex;
        color: #fff;
        justify-content: space-between;
        &-fffItem{
            font-family: SourceHanSansCN-Medium;
            font-size: 14px;
        }
        &-fffItemUnit{
            font-family: SourceHanSansCN-Medium;
            font-size: 12px;
        }
    }
}
</style>

rightProcess.vue

<template>
  <div class="hair-salon-bar-container">
    <div class="process">
      <div
        :style="{
          width: `${value.value}`,
          background:
            'linear-gradient(90deg,' +
            value.color[0] +
            ' 0%,' +
            value.color[1] +
            ' 100%)',
        }"
        class="bar"
      ></div>
    </div>
    <div class="pro-title">
      <span style="font-size: 18px; line-height: 12px">{{ value.name }}</span>
      <span
        style="font-size: 18px"
        class="pro-rate"
        :style="{ color: value.color[1] }"
        >{{ value.value }}</span
      >
    </div>
  </div>
</template>

<script>
export default {
  name: "processItem",
  props: {
    value: {
      type: Object,
      default: () => {},
    },
  },
  //   computed: {
  //     rateWidth() {
  //       if (this.width >= 100) {
  //         return 100
  //       } else {
  //         return this.width
  //       }
  //     }
  //   }
};
</script>

<style lang="scss" scoped>
.process {
  width: 100%;
  margin-top: 20px;
  height: 6px;
  position: relative;
  cursor: pointer;
  vertical-align: middle;
  background-color: #202427;
  .bar {
    height: 6px;
    margin: auto;
    border-radius: 2px;
    background-color: #409eff;
    position: absolute;
    left: 0;
  }
}
.pro-title {
  margin-top: 10px;
  margin-bottom: 10px;
  font-size: 12px;
  font-family: SourceHanSansCN-Regular;
  color: #fff;
  letter-spacing: 2px;
  line-height: 10px;
}
.pro-rate {
  float: right;
  font-size: 14px;
  font-family: SourceHanSansCN-Bold;
  font-weight: bold;
}
</style>

scrollCount.vue

left-bg.png

right-bg.png

<template>
  <div class="chartNum">
    <div class="box-item" :style="{'color': color}" v-if="type == 0">
      <li :class="{'number-item-l': !isNaN(item), 'mark-item': isNaN(item) }"
        v-for="(item,index) in orderNum"
        :key="index">
          <span v-if="!isNaN(item)">
            <i ref="numberItem">0123456789</i>
          </span>
        <span class="comma" v-else>{{item}}</span>
      </li>
    </div>
    <div class="box-item" :style="{'color': color}" v-if="type == 1">
      <li :class="{'number-item-r': !isNaN(item), 'mark-item': isNaN(item) }"
        v-for="(item,index) in orderNum"
        :key="index">
          <span v-if="!isNaN(item)">
            <i ref="numberItem">0123456789</i>
          </span>
        <span class="comma" v-else>{{item}}</span>
      </li>
    </div>
  </div>
</template>
<script>
  export default {
      props: {
          count: {
              type: Number,
              default: 0
          },
          type: {
              type: Number,
              default: 0
          },
          color: {
              type:String,
              default: ''
          },
          height: {
            type:String,
              default: ''
          }
      },
    data() {
      return {
        orderNum: ['0', '0', '0', '0', '0'], // 默认订单总数
      }
    },
    mounted(){
      setTimeout(() => {
        this.toOrderNum(this.count) // 这里输入数字即可调用
      }, 500);
    },
    methods: {
        // 设置文字滚动
      setNumberTransform () {
       const numberItems = this.$refs.numberItem // 拿到数字的ref,计算元素数量
       const numberArr = this.orderNum.filter(item => !isNaN(item))
       // 结合CSS 对数字字符进行滚动,显示订单数量
       for (let index = 0; index < numberItems.length; index++) {
        const elem = numberItems[index]
        elem.style.transform = `translate(-50%, -${numberArr[index] * 10}%)`
       }
      },
      // 处理总订单数字
      toOrderNum(num) {
       num = num.toString()
       // 把订单数变成字符串
        if (num.length < 5) {
          num = '0' + num // 如未满八位数,添加"0"补位
          this.toOrderNum(num) // 递归添加"0"补位
        } else if (num.length === 5) {
          // 订单数中加入逗号
          // num = num.slice(0, 2) + ',' + num.slice(2, 5) + ',' + num.slice(5, 8)
          this.orderNum = num.split('') // 将其便变成数据,渲染至滚动数组
        } else {
          // 订单总量数字超过八位显示异常
          this.$message.warning('总量数字过大')
        }
        this.setNumberTransform()
      },
    }
  }
</script>
<style scoped lang='scss'>
$url: "~@/assets/cluesFound";
   /*订单总量滚动数字设置*/
  .box-item {
    position: relative;
    // height: 40px;
    height: 3vh;
    font-size: 28px;
    line-height: 41px;
    text-align: center;
    list-style: none;
    color: #2D7CFF;
    writing-mode: vertical-lr;
    text-orientation: upright;
    /*文字禁止编辑*/
    -moz-user-select: none; /*火狐*/
    -webkit-user-select: none; /*webkit浏览器*/
    -ms-user-select: none; /*IE10*/
    -khtml-user-select: none; /*早期浏览器*/
    user-select: none;
    /* overflow: hidden; */
  }
  /* 默认逗号设置 */
  .mark-item {
    width: 10px;
    height: 40px;
    margin-right: 5px;
    line-height: 10px;
    font-size: 26px;
    position: relative;
    & > span {
      position: absolute;
      width: 100%;
      bottom: 0;
      writing-mode: vertical-rl;
      text-orientation: upright;
    }
  }
  /*滚动数字设置*/
  .number-item-l {
    width: 27px;
    height: 37px;
    /* 背景图片 */
    background: url('#{$url}/right-bg.png') no-repeat center center;
    background-size: 100% 100%;
    list-style: none;
    margin-right: 5px;
    // background:rgba(250,250,250,1);
    border-radius:4px;
    & > span {
      position: relative;
      display: inline-block;
      margin-right: 10px;
      width: 100%;
      height: 100%;
      writing-mode: vertical-rl;
      text-orientation: upright;
      overflow: hidden;
      & > i {
        font-style: normal;
        position: absolute;
        top: 3px;
        left: 45%;
        transform: translate(-50%,0);
        transition: transform 1s ease-in-out;
        letter-spacing: 10px;
      }
    }
  }
   /*滚动数字设置*/
  .number-item-r {
    width: 27px;
    height: 37px;
    /* 背景图片 */
    background: url('#{$url}/left-bg.png') no-repeat center center;
    background-size: 100% 100%;
    list-style: none;
    margin-right: 5px;
    // background:rgba(250,250,250,1);
    border-radius:4px;
    & > span {
      position: relative;
      display: inline-block;
      margin-right: 10px;
      width: 100%;
      height: 100%;
      writing-mode: vertical-rl;
      text-orientation: upright;
      overflow: hidden;
      & > i {
        font-style: normal;
        position: absolute;
        top: 3px;
    left: 45%;
        transform: translate(-50%,0);
        transition: transform 1s ease-in-out;
        letter-spacing: 10px;
      }
    }
  }
  .number-item:last-child {
    margin-right: 0;
  }
</style>