自动循环滚动消息列表

本文介绍了如何在Vue项目中使用自定义组件`auto-scroll`实现列表的自动无限循环滚动,以及如何设置滚动速度、间隔时间,以达到无缝滚动和动画效果。
摘要由CSDN通过智能技术生成

参考链接:vue组件:列表自动无限循环_vue 列表循环滚动-CSDN博客

vue-seamless-scroll插件不完全适合项目应用场景。

封装组件auto-scroll

<template>
    <div class="scroll-outer" ref="outer" @mouseover="onMouseover" @mouseleave="onMouseleave">
      <div class="scroll-inner-box" ref="scrollBox">
        <div class="scroll-item-box" ref="scrollItemBox">
          <slot></slot>
        </div>
        <div v-if="showSecond" class="scroll-item-box">
          <slot></slot>
        </div>
      </div>
    </div>
  </template>
    <script>
  export default {
    name: "auto-scroll",
    props: {
      list: {
        type: Array,
        default: () => [
          { name: "张三1" },
          { name: "张三2" },
          { name: "张三3" },
          { name: "张三4" },
          { name: "张三5" },
          { name: "张三6" },
          { name: "张三7" },
          { name: "张三8" },
          { name: "张三9" },
          { name: "张三10" },
        ],
      },
      speed: {
        type: Number,
        default: 0.1,
      },
      //滚动作单步运动时的单纯运动距离
      singleHeight: {
        type: Number,
        default: 0,
      },
      //单步运动的时间间隔
      waitTime: {
        type: Number,
        default: 0,
      },
    },
    data() {
      return {
        rafId: null,
        y: 0,
        showSecond: false,
        controleHeight: 0,
      };
    },
    watch: {
      list: {
        handler(newVal) {
          var that = this;
          this.$nextTick(() => {
            console.log(newVal);
            if (newVal && newVal.length > 0) {
              let scrollBox = that.$refs.scrollBox;
              let outer = that.$refs.outer;
   
              if (this.myReq) {
                cancelAnimationFrame(this.myReq);
              }
              // 开启动画
              if (this.canRun()) this.reqAnimationFrame();
              // this.reqAnimationFrame();
              // 手动滚动到底部时滚动条重置到最上边,同时滚动盒子重置为top:0
              outer.addEventListener("scroll", function () {
                if (
                  outer.scrollTop + outer.clientHeight + 4 >=
                  outer.scrollHeight
                ) {
                  outer.scrollTop = 0;
                  that.y = 0;
                  scrollBox.style.top = 0;
                }
              });
            }
          });
        },
        deep: true,
        immediate: true,
      },
    },
    mounted() {
      window.addEventListener("resize", this.listenResizeFn);
    },
    methods: {
      listenResizeFn() {
        cancelAnimationFrame(this.myReq);
        if (this.canRun()) this.reqAnimationFrame();
      },
      onMouseover() {
        clearTimeout(this.timer);
        cancelAnimationFrame(this.myReq);
      },
      onMouseleave() {
        if (this.canRun()) this.reqAnimationFrame();
      },
      canRun() {
        let scrollItemBox = this.$refs.scrollItemBox;
        let scrollBox = this.$refs.scrollBox;
        let outer = this.$refs.outer;
        // 开启动画条件:滚动盒子(scrollBox)高度高于外层容器(outer)高度
        if (outer.offsetHeight >= scrollItemBox.offsetHeight) {
          this.showSecond = false;
          outer.scrollTop = 0;
          this.y = 0;
          scrollBox.style.top = 0;
          return false;
        } else {
          this.showSecond = true;
          return true;
        }
      },
      //获取dom元素的高度:content+padding+margin+border
      getComputedHeight(dom) {
        let computedStyle = getComputedStyle(dom);
   
        let computedHeight =
          dom.offsetHeight +
          parseFloat(computedStyle.marginTop) +
          parseFloat(computedStyle.marginBottom);
        return computedHeight;
      },
      reqAnimationFrame() {
        //外层容器
        let outer = this.$refs.outer;
        //滚动盒子
        let scrollBox = this.$refs.scrollBox;
        //滚动盒子下边的第一个scroll-item-box,
        let scrollItemBox = this.$refs.scrollItemBox;
   
        //滚动速度
        this.speed = this.speed > 1 ? 1 : this.speed < 0 ? 0.1 : this.speed;
   
        //取第一个scrollItemBox高度
        let definedHeight = this.getComputedHeight(scrollItemBox);
        //持续滚动
        this.y = this.y + this.speed;
        scrollBox.style.top = -this.y + "px";
   
        //====添加滚动间隔控制====开始
        if (this.singleHeight >= 20 && this.waitTime > 500) {
          if (this.controleHeight >= this.singleHeight) {
            cancelAnimationFrame(this.myReq);
            this.controleHeight = 0;
            this.timer = setTimeout(() => {
              if (this.canRun) this.reqAnimationFrame();
            }, this.waitTime);
            return;
          } else {
            // 一次移动高度未达到指定距离继续执行动画
            this.controleHeight += this.speed;
          }
        }
        //====添加滚动间隔控制====结束
   
        //当滚动到第一个scroll-item-box高度时scrollBox重置为top:0,视觉上是无缝滚动
        if (this.y >= definedHeight) {
          this.y = 0;
        }
        this.myReq = window.requestAnimationFrame(this.reqAnimationFrame);
      },
    },
    destroyed() {
      window.removeEventListener("resize", this.listenResizeFn);
      cancelAnimationFrame(this.myReq);
      if (this.timer) clearTimeout(this.timer);
    },
  };
  </script>
    <style lang="less" scoped="scoped">
  .scroll-outer {
    height: 100%;
    overflow: hidden;
    // overflow-x: hidden;
    position: relative;
    &::-webkit-scrollbar {
      width: 0.3vw;
    }
    &:hover::-webkit-scrollbar-track {
      -webkit-box-shadow: inset 0 0 0.1vw rgba(0, 0, 0, 0.3);
      border-radius: 0.1vw;
      background-color: #295099;
      opacity: 1;
      display: none;
    }
    &:hover::-webkit-scrollbar-thumb {
      opacity: 1;
      border-radius: 0.1vw;
      -webkit-box-shadow: inset 0 0 0.1vw rgba(0, 0, 0, 0.3);
      background-color: #0ba9ea;
    }
  }
  .scroll-inner-box {
    height: auto;
    position: absolute;
    width: 100%;
    top: 0;
    left: 0;
  }
  </style>
    

使用:

<template>
  <div class="autoScroll">
    <autoScroll :list="recordMessages" :speed="0.5" :singleHeight="100">
      <div class="listItem" v-for = '(item,index) in recordMessages' :key="index+item">
        <span>{{item}}</span>
      </div>
    </autoScroll>
  </div>
</template>
    
<script>
import autoScroll from "../components/right/autoScroll.vue";
 
export default {
  components: {autoScroll},
  data() {
    return {
      recordMessages:[
        '消息消息消息消息消息消息消息消息消息消息消息111111111111111',
        '消息消息消息消息消息消息消息消息消息消息消息2222222222222222222222222',
        '消息消息消息消息消息消息消息消息消息消息消息333333333333333333333333333333333333333333333',
      ],
    };
  },
};
</script>
    
<style type="text/css" lang="less" scoped="scoped">
.autoScroll{
    height: calc(47% - 10px);
    padding: 0 10px;
    overflow: hidden;
    .listItem {
      width: 100%;
      background: rgba(69, 140, 201, 0.1);
      border-radius: 4px;
      margin-top: 10px;
      padding: 0px 10px 5px 10px;
      position: relative;
      animation: scroll 5s linear infinite; /* 设置动画 */
      span {
        font-weight: 400;
        font-size: 12px;
        text-align: left;
        color: #fff;
        opacity: 0.7;
      }
    }
}
</style>

效果:

消息滚动

注意:

  1. 参数waitTIme和singleHeight同时存在,才能出现滚动动画间隔执行的效果 
  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值