vue3 实现列表的无限循环滚动

通过vue3-seamless-scroll实现

安装vue3-seamless-scroll

 npm install vue3-seamless-scroll --save

使用

<!--组件.vue-->
<script setup lang="ts">
import { Vue3SeamlessScroll } from 'vue3-seamless-scroll';
import { ref } from 'vue'
//vue3导入组件是不需要用component注册的
//导入完成后如果项目本身是在运行的记得重新编译项目,不然会报错,如npm run dev
const listData = ref([
  { Connected: true, StationName: '油箱托架', EquipmentName: 'VISION-4', Torque: '320Nm', Angle: '98°', status: 'ok', Alarm: true, Time: '08:43:20' },
  { Connected: true, StationName: '平衡轴', EquipmentName: 'VISION-9L01', Torque: '420Nm', Angle: '89°', status: 'ok', Alarm: true, Time: '08:43:30' },
  { Connected: true, StationName: '平衡轴', EquipmentName: 'VISION-9L02', Torque: '320Nm', Angle: '92°', status: 'ok', Alarm: true, Time: '08:43:25' },
  { Connected: true, StationName: '平衡轴', EquipmentName: 'VISION-9R', Torque: '270Nm', Angle: '87°', status: 'ok', Alarm: true, Time: '08:43:23' },
  { Connected: true, StationName: '平衡轴', EquipmentName: 'VISION-9M', Torque: '450Nm', Angle: '80°', status: 'ok', Alarm: true, Time: '08:43:28' },
  { Connected: true, StationName: '前桥U型', EquipmentName: 'TWIN-17', Torque: '720Nm', Angle: '90°', status: 'ok', Alarm: true, Time: '08:43:50' },
  { Connected: true, StationName: '前板簧销拧紧', EquipmentName: 'VISION-4', Torque: '920Nm', Angle: '82°', status: 'ok', Alarm: true, Time: '08:45:20' },
  { Connected: true, StationName: '单后桥U型螺栓', EquipmentName: 'TWIN-20', Torque: '820Nm', Angle: '89°', status: 'ok', Alarm: true, Time: '08:43:40' },
  { Connected: true, StationName: '后板簧销、减震器拧紧 ', EquipmentName: 'VISION-22', Torque: '620Nm', Angle: '88°', status: 'ok', Alarm: true, Time: '08:43:24' },
  { Connected: true, StationName: '前悬扭杆机构拧紧', EquipmentName: 'SC022317002', Torque: '220Nm', Angle: '96°', status: 'ok', Alarm: true, Time: '08:43:27' },
  { Connected: true, StationName: '鞍座', EquipmentName: 'VISION-4', Torque: '220Nm', Angle: '98°', status: 'ok', Alarm: true, Time: '08:43:50' },
  { Connected: true, StationName: '传动轴与后桥', EquipmentName: 'SC022311008', Torque: '220Nm', Angle: '89°', status: 'ok', Alarm: true, Time: '08:42:23' },
  { Connected: true, StationName: '传动轴吊挂', EquipmentName: 'SC022317002', Torque: '280Nm', Angle: '92°', status: 'ok', Alarm: true, Time: '08:40:12' },
  { Connected: true, StationName: '转向器输入轴', EquipmentName: 'CONNECT-38', Torque: '68Nm', Angle: '87°', status: 'ok', Alarm: true, Time: '08:48:32' },
  { Connected: true, StationName: '轮胎螺栓拧紧', EquipmentName: 'TWIN-43L', Torque: '480Nm', Angle: '80°', status: 'ok', Alarm: true, Time: '08:43:43' },
  { Connected: true, StationName: '轮胎螺栓', EquipmentName: 'TWIN-43R', Torque: '467Nm', Angle: '80°', status: 'ok', Alarm: true, Time: '08:43:21' },
  { Connected: true, StationName: '离合器压盘、高压线', EquipmentName: 'CONNECT-0101', Torque: '56Nm', Angle: '90°', status: 'ok', Alarm: true, Time: '08:45:12' },
  { Connected: true, StationName: '发动机与变速箱', EquipmentName: 'CONNECT-0102', Torque: '60Nm', Angle: '82°', status: 'ok', Alarm: true, Time: '08:41:32' },
  { Connected: true, StationName: '发动机与变速箱', EquipmentName: 'CONNECT W', Torque: '65Nm', Angle: '89°', status: 'ok', Alarm: true, Time: '08:46:13' },
])
const isScroll = ref(true)
</script>
<template>
  <div class="contain">
    <!-- <el-card shadow="never"> -->
    <div class="monitor panel">
      <div style="height: 95%;overflow: hidden;">
        <div class="content" style="display: block;">
          <div class="head">
            <span class="col" style="width: 15%;">设备开启状态</span>
            <span class="col" style="width: 10%;">工位名称</span>
            <span class="col" style="width: 10%;">设备名称</span>
            <span class="col" style="width: 10%;">扭矩</span>
            <span class="col" style="width: 10%;">角度</span>
            <span class="col" style="width: 10%;">连接状态</span>
            <span class="col" style="width: 10%;">拧紧结果</span>

            <span class="col" style="width: 10%;">报警状态</span>
            <span class="col" style="width: 15%;">记录时间</span>
          </div>
        </div>
        <div class="seamlessRolling">
          <div class="maps">
            <img src="@/assets/images/lbx.png" alt="" class="map">
            <img src="@/assets/images/jt.png" alt="" class="map1">
            <img src="@/assets/images/map.png" alt="" class="map2">
          </div>
          <Vue3SeamlessScroll class="scroll" v-model="isScroll" :list="listData" :step="0.3" :hover="true"
            :limit-scroll-num="3" :wheel="true">
            <ul>
              <li v-for="(item, index) in listData" :key="index" class="row">
                <span class="col" style="width: 15%; font-size: 30px;">
                  <el-icon>
                    <Open />
                  </el-icon>
                </span>
                <span class="col" style="width: 10%;">
                  {{ item.StationName }}
                </span>
                <span class="col" style="width: 10%;">{{ item.EquipmentName
                }}</span>
                <span class="col" style="width: 10%;">{{ item.Torque ? item.Torque : 'null' }}</span>
                <span class="col" style="width: 10%;">{{ item.Angle ? item.Angle : 'null' }}</span>
                <span class="col" style="width: 10%;">{{
                  item.Connected ? 'ON' : 'OFF'
                }}</span>
                <span class="col" style="width: 10%;">{{ item.status }}</span>
                <span class="col" style="width: 10%;"><span :class="item.Alarm ? 'bgdccc' : 'bgdref'"></span></span>
                <span class="col" style="width: 15%;">{{ item.Time }}</span>
              </li>
            </ul>
          </Vue3SeamlessScroll>
        </div>
      </div>
    </div>

    <!-- </el-card> -->
  </div>
</template>
<style lang='scss' scoped>
.contain {
  width: 97%;
  margin: 10px auto;
  border-radius: 10px;
  height: 620px;
  overflow: hidden;
  background: url("@/assets/images/53bg.png") no-repeat;
  background-size: 100% 100%;
}

.seamlessRolling {
  margin: 0 auto;
  width: 100%;
  height: 100%;
  overflow: hidden;
  text-shadow: 0 0 25px #00fbfe;
  position: relative;

  .maps {
    // position: absolute;
    // width: 100%;
    // height: 100%;

    .map {
      position: absolute;
      top: 5%;
      left: 35%;
      width: 30rem;
      animation: myfirst 10s infinite linear;
    }

    .map1 {
      position: absolute;
      top: 6%;
      left: 38%;
      width: 26rem;
      animation: myfirst 10s infinite linear;
      z-index: 9;
    }

    .map2 {
      position: absolute;
      top: 7%;
      left: 38%;
      width: 25rem;
      animation: myfirst 10s infinite linear;
      opacity: .7;
    }
  }



  .row:nth-child(odd) {
    color: #00fbfe;
  }

  .row:nth-child(even) {
    color: #ffd700;
  }
}

/* 监控 */
.monitor {
  box-sizing: border-box;
}

.monitor .content {
  flex: 1;
  display: none;
  position: relative;
}

.monitor .head {
  background: rgba(255, 255, 255, 0.1);
  font-size: 20px;
  padding: 0.5rem 1.5rem;
  display: flex;
  justify-content: space-between;
  line-height: 1.05;
  text-align: center;
  color: #ffd700 !important;
  text-shadow: 0 0 25px #00fbfe;
}

.monitor .row {
  line-height: 1.05;
  padding: 0.5rem 1.5rem;
  font-size: 16px;
  position: relative;
  display: flex;
  justify-content: space-between;
  text-align: center;
  align-items: center;
}

.monitor .row:hover {
  background: rgba(255, 255, 255, 0.1);
}


@media screen and (min-width: 2000px) {
  html {
    font-size: 40px;
  }
}

@keyframes myfirst {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(-359deg);
  }
}

.on {
  background-color: green;
  padding: 5px 10px;
  color: #fff !important;
  border-radius: 3px;
}

.off {
  background-color: red;
  padding: 5px 10px;
  color: #fff !important;
  border-radius: 3px;
}

.green {
  color: green;
}

.bgdccc {
  width: 1.5rem;
  height: 1.5rem;
  background-color: #ccc;
  display: block;
  margin: 0 auto;
  border-radius: 50%;
}

.bgdref {
  width: 1.5rem;
  height: 1.5rem;
  background-color: red;
  display: block;
  margin: 0 auto;
  border-radius: 50%;
}
</style>

组件配置

type:可选参数,required:是否必填

  • list

    无缝滚动列表数据,组件内部使用列表长度。

      type: Array
      required: true
  • v-model

    通过v-model控制动画滚动与停止,默认开始滚动

      type: Boolean,
      default: true,
      required: false
  • direction

    控制滚动方向,可选值updownleftright

      type: String,
      default: "up",
      required: false
  • isWatch

    开启数据更新监听

      type: Boolean,
      default: true,
      required: false
  • hover

    是否开启鼠标悬停

      type: Boolean,
      default: false,
      required: false
  • count

    动画循环次数,默认无限循环

      type: Number,
      default: "infinite",
      required: false
  • limitScrollNum

    开启滚动的数据量,只有列表长度大于等于该值才会滚动

      type: Number,
      default: 5,
      required: false
  • step

    步进速度

      type: Number,
      required: false
  • singleHeight

    单步运动停止的高度

      type: Number,
      default: 0,
      required: false
  • singleWidth

    单步运动停止的宽度

      type: Number,
      default: 0,
      required: false
  • singleWaitTime

    单步停止等待时间(默认值 1000ms)

      type: Number,
      default: 1000,
      required: false
  • isRemUnit

    singleHeight and singleWidth 是否开启 rem 度量

      type: Boolean,
      default: true,
      required: false
  • delay

    动画延时时间

      type: Number,
      default: 0,
      required: false
  • ease

    动画效果,可以传入贝塞尔曲线数值

      type: String | cubic-bezier,
      default: "ease-in",
      required: false
  • copyNum

    拷贝列表次数,默认拷贝一次,当父级高度大于列表渲染高度的两倍时可以通过该参数控制拷贝列表次数达到无缝滚动效果

      type: Number,
      default: 1,
      required: false
  • wheel

    在开启鼠标悬停的情况下是否开启滚轮滚动,默认不开启

      type: boolean,
      default: false,
      required: false
  • singleLine

    启用单行横向滚动

      type: boolean,
      default: false,
      required: false

示例

<iframe id="nEFL8Isc-1705655330122" frameborder="0" src="//i2.wp.com/live.csdn.net/v/embed/360597" allowfullscreen="true" data-mediaembed="csdn"></iframe>

vue3 实现列表的无限循环滚动