效果图如下:
思路:
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>
以上就是大概的实现,有什么问题环境评论指出