最近遇到这么一个需求,就是内容一行显示,滚轮滚动的时候,进行横向滚动。

本来想尝试下css能不能做到,最后发现,即便改变了流的布局,并不能改变滚动条的方向,最后还是只能用js做了。

滚动兼容性

滚轮只存在pc的时候,所以触摸事件是不考虑的,触摸的话可以直接用better-scroll插件。

滚动事件需要兼容火狐和谷歌:

  1. 火狐滚动事件:DOMMouseScroll
  2. 谷歌滚动事件:mousewheel

其中DOMMouseScroll的event对象,他有一个detail字段,向下滚动是3,往上滚动是-3

mousewheel的event对象是deltaY,往下滚动是125,往上是-125,具体数值记不清了,反正是这样。

兼容的情况就是这样了,字段不同。

组件代码

创建一个CrosswiseScroll.vue组件

调整:当不能横向滚动时,可以触发上下滚动,如果横向滚动到底了,会延迟一会,然后恢复滚轮上下滚动功能

代码如下:

<template>
  <div class="crosswise-scroll" @DOMMouseScroll.prevent="mouseTranslate" @mousewheel="mouseTranslate">
    <div class="crosswise-content" ref="crosswiseContent"
      :style="'transform: translateX(' + translateX + 'px);'">
      <slot></slot>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      translateX: 0, //滚动的距离
      maxTranslateX: 0, //最大滚动距离
      flag: false,
    };
  },
  methods: {
    // 鼠标滚轮滑动事件
    mouseTranslate(event) {
      //没有最大滚动宽度进行计算
      if (!this.maxTranslateX) this.countMaxTranslateX();
      if (this.maxTranslateX <= 0) return;
      const delta = event.deltaY || event.detail;
      let x = this.translateX;
      if (delta > 0) {
        x =
          Math.abs(x - 100) >= this.maxTranslateX
            ? -this.maxTranslateX
            : x - 100;
      } else {
        x = x + 100 >= 0 ? 0 : x + 100;
      }
      this.translateX = x;
      console.log(this.translateX);
      if (
        this.translateX === 0 ||
        Math.abs(this.translateX) === this.maxTranslateX
      ) {
        clearTimeout(this.$timer);
        this.$timer = setTimeout(() => {
          this.flag = true;
        }, 300);
      } else {
        this.flag = false;
      }
      if (!this.flag) event.preventDefault();
    },
    //计算最大滚动距离
    countMaxTranslateX() {
      if (!this.crosswiseContent) {
        this.crosswiseContent = this.$refs.crosswiseContent;
      }
      this.maxTranslateX =
        this.crosswiseContent.scrollWidth - this.crosswiseContent.offsetWidth;
      if (Math.abs(this.translateX) >= this.maxTranslateX) {
        this.translateX = -this.maxTranslateX;
      }
    },
  },
  created() {
    //计算最大滚动距离
    // this.$nextTick(() => {
    //   this.countMaxTranslateX();
    // });
  },
  mounted() {
    window.addEventListener("resize", this.countMaxTranslateX, false);
  },
  beforeDestroy() {
    window.removeEventListener("resize", this.countMaxTranslateX, false);
  },
};
</script>
<style lang="scss" scoped>
.crosswise-scroll {
  overflow-x: hidden;
  .crosswise-content {
    transition: transform 0.1s;
  }
}
</style>

使用

<template>
  <crosswise-scroll>
    ...需要横向滚动显示的内容
  </crosswise-scroll>
</template>
<script>
  import CrosswiseScroll from "CrosswiseScroll";
  export default {
    components: {
      CrosswiseScroll,
    }
  }
</script>

注意:

  1. 横向滚动的内容自身不能overflow: hidden

简单点来理解就是,横向滚动的内容就是内容的实际宽度,他可以超出容器宽度,因为我们横向滚动就是为了应对这种情况的。

分类: vue 项目实战 标签: vue横向滚动DOMMouseScrollmousewheeldeltaYdetail

评论

暂无评论数据

暂无评论数据

目录