区块-自动自下向上移动(字幕滚动)

发布时间 2023-11-10 16:03:10作者: 球球啦啦啦

示例图

引入组件

import autoScroll from './components/autoMove.vue'

 页面使用组件

<div class="pro-body">
   <autoScroll  :list="kzProData.specialCareList"
                :speed="kzProSpeed"
                 :waitTime="0"
                 :singleHeight="100"
                  >
          <div class="t-item">
              <div
                 class="t-value"
                  v-for="(item, index) in kzProData.specialCareList"
                  key="index"
                 >
                    <span> {{ item.zxhlxmmc || '--' }}</span>
               </div>
            </div>
   </autoScroll>
</div>

// 部分样式
<style scoped lang="scss">
.pro-body {
  height: 80%;

  .t-item {
    width: 100%;
  }

  .t-value {
    text-align: center;
    height: 2.5rem;
    line-height: 2.5rem;
    background: linear-gradient(
      90deg,
      rgba(129, 228, 251, 0) 0%,
      rgb(113 219 249 / 0.2) 15%,
      rgb(8 144 255 / 0.2) 52%,
      rgb(74 197 245 / 0.2) 83%,
      rgba(74, 197, 245, 0) 100%
    );
    border-radius: 3px;
    margin-top: 0.4rem;
    color: #133554;
    font-size: 1.1rem;
    font-weight: 400;
    overflow: hidden;
  }
}
</style>

组件代码

<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: "my-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="scss">
  .scroll-outer {
    height: 100%;
    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>