自定义滚动条+页面回弹效果

效果图如下:

 思路:

1.给图片增加上拉回弹效果

2.给列表增加 下拉回弹效果

==》以上实现回弹效果

3.自定义一个滚动条,写死滚动条的大小,以及滚动块的大小

4.在上拉回弹和下拉回弹的方法里面添加可以让滚动块滚动的top值

思路:滚动的距离/页面总的高度 = 要获得的top值/滚动条的高度

代码实现如下:

<template>
  <div class="box" ref="box">
    <!-- 滚动条 -->
    <div class="scrollBar"><i ref="bar" /></div>
    <div class="root bounce" ref="root">
      <!-- 图片 -->
      <div
        class="topbg"
        ref="topbg"
        @touchstart.stop="handlerTouchStart"
        @touchmove.stop="handlerTouchMove"
        @touchend.stop="handlerTouchEnd"
      >
        <img src="../src/assets/1.jpg" alt="" />
      </div>
      <!-- 列表 -->
      <div
        class="lists"
        ref="lists"
        @touchstart.stop="handlerTouchListStart"
        @touchmove.stop="handlerTouchListMove"
        @touchend.stop="handlerTouchListEnd"
        @scroll="onScroll"
      >
        <div v-for="(item, index) in list" :key="index" class="item">
          {{ item.name }}
        </div>
      </div>
    </div>
  </div>
</template>

css代码:

<style lang="less">
html,
body,
#app {
  height: 100vh;
  width: 100vw;
  padding: 0;
  margin: 0;
  background: #ededed;
  overflow: hidden;
}
.box {
  width: 100vw;
  height: 100vh;
}
.root {
  overflow: auto;
  &::-webkit-scrollbar {
    width: 0px !important;
    display: none !important;
  }
}
.item {
  width: 100vw;
  height: 100px;
  background: #fff;
}
.topbg {
  width: 100vw;
  height: 764px;
  img {
    width: 100%;
    height: 100%;
  }
}
.lists {
  background: #fff;
  height: 100vh;
  overflow: auto;
  &::-webkit-scrollbar {
    width: 0px !important;
    display: none !important;
  }
}
.root.bounce {
  transition-property: transform;
  transition-duration: 0.5s;
  transition-timing-function: ease-out;
}

.scrollBar {
  position: fixed;
  right: 10px;
  top: 100px;
  height: 200px;
  width: 8px;
  border-radius: 10px;
  background: pink;
  opacity: 0.5;
  z-index: 10;
  i {
    position: absolute;
    left: 0;
    top: 0;
    width: 8px;
    height: 50px;
    background: #000;
    border-radius: 10px;
    transform: all 0.5s ease-out;
  }
}
</style>

js代码实现:

<script>
const list = [
  {
    name: "111"
  },
  {
    name: "111"
  },
  {
    name: "111"
  },
  {
    name: "111"
  },
  {
    name: "111"
  },
  {
    name: "111"
  },
  {
    name: "111"
  },
  {
    name: "111"
  },
  {
    name: "111"
  },
  {
    name: "111"
  },
  {
    name: "111"
  },
  {
    name: "111"
  },
  {
    name: "111"
  },
  {
    name: "111"
  }
];
export default {
  data() {
    return {
      baseTop: 0, //记录滚出第一屏后的top值
      bounceDistance: 200, //弹性距离
      startLocation: 0,
      height: 764, //浏览器高度,写死了,要是兼容手机可以js获取页面的高度
      moveDistance: 0,
      isBouncing: false, //是否开启弹性效果
      pageHeight: 0, //页面总高度
      barHeight: 200 //滚动条自定义高度
    };
  },
  mounted() {
    this.$nextTick(() => {
      this.pageHeight = this.$refs.root.offsetHeight;
    });
  },
  methods: {
    handlerTouchStart(e) {
      this.startLocation = e.touches[0].pageY;
    },
    handlerTouchMove(e) {
      this.moveDistance = Math.floor(e.touches[0].pageY - this.startLocation);
      if (this.moveDistance < 0) {
        this.$refs.root.style.transform = `translateY(${this.moveDistance}px)`;
        // 滚动条转换比例
        let top =
          (this.barHeight * Math.abs(this.moveDistance)) / this.pageHeight;
        this.$refs.bar.style.top = Math.floor(top) + "px";
      }
    },
    handlerTouchEnd(e) {
      if (Math.abs(this.moveDistance) <= this.bounceDistance) {
        this.$refs.root.style.transform = "translateY(0px)";
        this.$refs.bar.style.top = "0px";
      } else {
        this.$refs.root.style.transform = `translateY(-${this.height}px)`;
        // 重置滚动条top
        let top =
          (this.barHeight * Math.abs(this.moveDistance)) / this.pageHeight;
        this.baseTop = Math.floor(top);
        this.$refs.bar.style.top = Math.floor(top) + "px";
      }
    },
    handlerTouchListStart(e) {
      if (this.isBouncing) return;
      this.startLocation = e.touches[0].pageY;
    },
    handlerTouchListMove(e) {
      if (this.isBouncing) return;
      this.moveDistance = Math.floor(e.touches[0].pageY - this.startLocation);
      if (this.moveDistance > 0) {
        this.$refs.root.style.transform = `translateY(${
          -this.height + this.moveDistance
        }px)`;
        // 滚动条转换比例
        let top =
          (this.barHeight * Math.abs(this.moveDistance)) / this.pageHeight;
        // 当前滚动条的top值
        const currentTop = this.baseTop;
        this.$refs.bar.style.top = Math.floor(currentTop - top) + "px";
      }
    },

    handlerTouchListEnd(e) {
      // 阻止向上滑动时触发弹性效果
      if (this.isBouncing) return;
      if (this.moveDistance <= this.bounceDistance) {
        this.$refs.root.style.transform = `translateY(-${this.height}px)`;
        // 重置滚动条top
        this.$refs.bar.style.top = this.baseTop + "px";
      } else {
        this.$refs.root.style.transform = "translateY(0)";
        this.$refs.bar.style.top = "0px";
      }
    },
    onScroll() {
      this.isBouncing = this.$refs.lists.scrollTop > 100;
      //  滚动条转换比例
      const bar = this.barHeight - 50; //50是小滚动条的高度
      const surplusListsHeight = this.pageHeight - this.height;
      let top = (bar * this.$refs.lists.scrollTop) / surplusListsHeight;
      // 200是大概到底部的距离
      if (this.$refs.lists.scrollTop + 200 > surplusListsHeight) {
        this.$refs.bar.style.top = bar + "px";
      } else {
        this.$refs.bar.style.top = Math.floor(top) + 50 + "px";
      }
    }
  }
};
</script>

以上就是大概的实现,有什么问题环境评论指出

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值