封装一个丝滑的自动滚动组件

本文介绍了一个名为my-auto-scroll的Vue组件,用于实现自动滚动效果。它监听列表变化并使用CSStransform进行优化,确保滚动流畅且无缝。组件接受一个数组作为props,展示了如何在模板中使用和CSS样式定制。
摘要由CSDN通过智能技术生成

封装一个    autoScroll.js组件 

<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' },
      ]
    },
  },
  data() {
    return {
      y: 0,
      speed: 0.4,
      showSecond: false,
    };
  },
  watch: {
    list: {
      handler(newVal) {
        var that = this;
        this.$nextTick(() => {
          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();
            // 手动滚动到底部时滚动条重置到最上边,同时滚动盒子重置为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
    }
  },
  methods: {
    // 鼠标移入 停止滚动
    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';


    //     //当滚动到第一个scroll-item-box高度时scrollBox重置为top:0,视觉上是无缝滚动
    //     if (this.y >= definedHeight) {
    //       this.y = 0;
    //     }
    //     this.myReq = window.requestAnimationFrame(this.reqAnimationFrame);
    //   }
    //


    //此处对滚动方法做了优化---上面的方法 滚动的时候会一帧一帧的 不够流畅
    //在实现滚动效果时,使用 CSS 的 transform: translateY() 属性通常比直接修改元素的 top 属性具有更好的性能。这是因为修改 transform 不会引起浏览器的重布局(reflow)和重绘(repaint),从而减少了性能开销。
    


    reqAnimationFrame() {
      let scrollBox = this.$refs.scrollBox;
      let scrollItemBox = this.$refs.scrollItemBox;

      // 取第一个scrollItemBox高度
      let definedHeight = this.getComputedHeight(scrollItemBox);

      // 持续滚动
      this.y += this.speed;

      // 使用 translate 替代 top 来改变位置
      scrollBox.style.transform = `translateY(-${this.y}px)`;

      // 当滚动到第一个scroll-item-box高度时scrollBox重置,视觉上是无缝滚动
      if (this.y >= definedHeight) {
        this.y = 0; // 重置滚动距离
        scrollBox.style.transform = 'translateY(0)'; // 重置位置
      }

      this.myReq = window.requestAnimationFrame(this.reqAnimationFrame.bind(this));
    },
  },
  destroyed() {
    cancelAnimationFrame(this.myReq);
    if (this.timer) clearTimeout(this.timer);
  }
};
</script>
<style lang="scss" scoped>
.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>

组件使用方法

<autoScroll :list="centerList">
  <div v-for="(item, index) in centerList" :key="index">
   {{item}}
  </div>
</autoScroll>

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值