14-PC端点击横向滚动

前提条件:做一个商品列表,不换行,超出长度是横向滚动,但不是通过滚动条,是点击左右按钮滚动商品列表

过程:

先做一个测试商品列表和左右点击按钮

实现效果:

1、当商品列表为初始状态或商品列表滚动回第一个时,左按钮隐藏,右按钮展示

2、当商品列表展示滚动到中间部分时,左右按钮皆展示

3、当商品列表展示滚动到最后一个时,左按钮展示,右按钮隐藏

完整代码(仅滚动,不跟踪)

<template>
  <div style="position: relative; margin: 20px">
    <div class="product-container" id="product" ref="product">
      <div>
        <div style="text-align: center; height: 100%" v-if="isLeftShow">
          <button class="leftBtn" @click="HorizontalScrolling('left')">
            <i class="el-icon-arrow-left"></i>
          </button>
        </div>
        <div class="productItem" v-for="n in 20" :key="n">商品 {{ n }}</div>
        <div style="text-align: center; height: 100%" v-if="isRightShow">
          <button class="rightBtn" @click="HorizontalScrolling('right')">
            <i class="el-icon-arrow-right"></i>
          </button>
        </div>
      </div>
    </div>
  </div>
</template>  
  
<script>
export default {
  data() {
    return {
      isLeftShow: false,
      isRightShow: true,
    };
  },
  methods: {
    HorizontalScrolling(type) {
      const allLength =  document.getElementsByClassName(`productItem`)[0].clientWidth * 20 - this.$refs.product.getBoundingClientRect().width
      if (type == "left") {
        this.$refs.product.scrollLeft -= 200;
        this.isRightShow = true;
        if (this.$refs.product.scrollLeft <= 200) {
          this.isLeftShow = false;
        }
      } else {
        this.$refs.product.scrollLeft += 200;
        this.isLeftShow = true;
        if (this.$refs.product.scrollLeft >=allLength) {
          this.isRightShow = false;
        }
      } 
    }
  },
};
</script>  
  
<style scoped>
.leftBtn {
  position: absolute;
  left: -10px;
  top: -2px;
  height: 105px;
  border-radius: 10px;
  background: white;
  padding: 2px;
  border: none;
}
.leftBtn:hover {
  background: #eee;
}
.rightBtn {
  position: absolute;
  right: -10px;
  top: -2px;
  height: 105px;
  border-radius: 10px;
  background: white;
  padding: 2px;
  border: none;
}
.rightBtn:hover {
  background: #eee;
}
.product-container {
  width: 100%;
  overflow-x: auto; 
  white-space: nowrap; 
  scroll-behavior: smooth;
}
.productItem {
  display: inline-block; 
  width: 100px; 
  height: 100px; 
  line-height: 100px; 
  text-align: center; 
  margin-right: 10px; 
  background-color: rgb(235, 150, 135); 
  border-radius: 10px;
}
/* 隐藏下方的滚动条 */
.product-container::-webkit-scrollbar {
  /* background-color: transparent; */
  display: none;
}
</style>

以上是仅滚动不跟踪商品位置的示例,如果想要滚动条跟着商品列滚动, 就要换种写法

在这种需求下,实现效果的条件就要改变一下

1、当商品列表为初始状态时,左按钮不隐藏,右按钮展示,左右按钮表示商品的上一个或下一个

2、当高亮商品为第一个时,左按钮隐藏,否则展示

3、当高亮商品是最后一个时,右按钮隐藏,否则展示

4、高亮商品必须展示在可见区域内

实现逻辑

1、计算当前可见区域内可展示的商品个数,取中间值

2、找到滚动条滚动值和商品位置的关系

可知,滚动条是在可视容器中滚动,则滚动条的区域长度即为可视容器的宽度(clientWidth),而商品列的实际宽度(scrollWidth)为商品展示宽度(包括元素宽度+margin)*商品个数,则滚动条的可滚动距离为商品列实际宽度-可视容器的宽度,滚动条移动的距离与内容滚动的距离之间的比率是恒定的

则可得出对应商品的滚动值 = 最大滚动值/商品总数*当前商品所在下标

3、当高亮商品的下标小于中间值时,滚动值为0

4、当高亮商品下标大于中间值,且小于总数-中间值+1时,滚动值为计算的滚动值

5、当高亮商品下标大于总数-中间值+1时,滚动值为最大滚动值

6、当点击左按钮直到下标为0时,左按钮隐藏

7、当点击右按钮直到下位为商品总数时,右按钮隐藏

以本次示例数据计算

商品总数:20

可视区域宽度(685):this.$refs.product.clientWidth 或 this.$refs.product.getBoundingClientRect().width

实际内容宽度(2200):this.$refs.product.scrollWidth 或(document.getElementsByClassName(`productItem`)[0].clientWidth +10)* 20

最大滚动值:实际内容宽度 - 可视区域宽度 = 1515

单个商品元素宽度:document.getElementsByClassName(`productItem`)[0].clientWidth

可见区域内可展示的商品个数:可视区域宽度/单个商品元素宽度=6.85,向上取整为7

具体代码如下:

    //滚动,跟踪商品位置
    HorizontalScrolling(type) {
      //可见区域内可展示的商品个数,向上取整,取中间值
      let center =
        Math.ceil(
          this.$refs.product.getBoundingClientRect().width /
            document.getElementsByClassName(`productItem`)[0].clientWidth
        ) / 2;
      //点击上一个
      if (type == "left") {
        this.currentIndex--; //下标-1
        this.isRightShow = true;
        if (this.currentIndex == 1) {
          this.isLeftShow = false;
        }
      } else {
        //点击下一个
        this.currentIndex++; //下标+1
        this.isLeftShow = true;
        if (this.currentIndex == 20) {
          this.isRightShow = false;
        }
      }
      //计算滚动值:最大滚动值/商品总数*当前商品所在下标
      // let scrollLeft =
      //   (document.getElementsByClassName(`productItem`)[0].clientWidth -
      //     this.$refs.product.getBoundingClientRect().width / 20 +
      //     10) *
      //   this.currentIndex;
      let scrollLeft =
        ((this.$refs.product.scrollWidth -
          this.$refs.product.getBoundingClientRect().width) /
          20) * this.currentIndex;
      if (this.currentIndex <= 20 - center + 1 && this.currentIndex > center) {
        this.$refs.product.scrollLeft = scrollLeft;
      } else if (this.currentIndex > 20 - center + 1) {
        // this.$refs.product.scrollLeft =
        //   (document.getElementsByClassName(`productItem`)[0].clientWidth -
        //     this.$refs.product.getBoundingClientRect().width / 20 +
        //     10) *
        //   20;
        this.$refs.product.scrollLeft =
          this.$refs.product.scrollWidth -
          this.$refs.product.getBoundingClientRect().width;
      } else {
        this.$refs.product.scrollLeft = 0;
      }
    }

效果如图:

坚持就是胜利!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值