wuliu_sy/components/you-scroll.vue

272 lines
6.0 KiB
Vue
Raw Normal View History

2023-11-28 08:59:04 +08:00
<template>
<view class="you-scroll" ref="youScroll">
<view class="pullDown" :style="{ transform: 'translateY('+translateY+'px)', transition: isDown ? '0s' : '0.3s' }">
<slot name="pullDown">
<!-- <img src="@/static/pullDown.jpg" :class="{'down-icon': true,'animate': pullDownStatus == 3}"></img> -->
<span>
<block v-if="pullDownStatus == 1">{{downPullToRefresh}}</block>
<block v-if="pullDownStatus == 2">{{downReleaseToRefresh}}</block>
<block v-if="pullDownStatus == 3">{{downRefreshing}}</block>
</span>
</slot>
</view>
2023-12-02 15:29:39 +08:00
<scroll-view class="you-scroll-inner" ref="youScrollInner" :scroll-top.stop="scrollToTop" scroll-with-animation scroll-y :style="{ transform: 'translateY('+translateY+'px)', transition: isDown ? '0s' : 'transform 0.3s' }"
@touchstart.stop="startFn" @touchmove.stop="moveFn" @touchend.stop="endFn" @touchcancel.stop="endFn" @scroll.stop="scroll">
2023-11-28 08:59:04 +08:00
<view class="you-scroll-content">
<slot></slot>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
data() {
return {
scrollToTop: 0,
scrollTop: 0,
oldTop: 0,
sPageY: 0,
mPageY: 0,
ePageY: 0,
translateY: 0,
pullDownStatus: 1, // 1下拉刷新 2松开刷新 3刷新中
isDown: false
};
},
props: {
pullDownDistance: {
type: Number,
default: 50 // 下拉刷新距离
},
reachBottomDistance: {
type: Number,
default: 30 // 上拉加载距离
},
downPullToRefresh: {
type: String,
default: '下拉刷新'
},
downReleaseToRefresh: {
type: String,
default: '松开刷新'
},
downRefreshing: {
type: String,
default: '刷新中…'
},
},
methods: {
startFn(e) {
this.isDown = true;
this.sPageY = e.changedTouches[0].pageY;
this.pointY = this.translateY;
},
moveFn(e) {
let view = uni.createSelectorQuery().in(this).select(".you-scroll-inner");
view.fields({
size: true,
scrollOffset: true
}, data => {
this.scrollTop = data.scrollTop;
this.mPageY = e.changedTouches[0].pageY;
if (this.scrollTop <= 0) {
let translateY = ((this.mPageY - this.sPageY) / 2) + this.pointY;
this.translateY = (translateY < 0 ? 0 : translateY);
if(this.pullDownStatus != 3) {
if(this.translateY < this.pullDownDistance) {
this.pullDownStatus = 1;
} else if(this.translateY >= this.pullDownDistance) {
this.pullDownStatus = 2;
}
}
}
}).exec();
},
endFn(e) {
this.isDown = false;
this.ePageY = e.changedTouches[0].pageY;
setTimeout(() => {
this.translateY = this.translateY >= this.pullDownDistance ? this.pullDownDistance : 0;
if(this.pullDownStatus == 2) { // 开始刷新
this.pullDownStatus = 3;
this.$emit('onPullDown',this.endPullDown);
}
},100)
},
endPullDown(mm) {
if(this.timeout) clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
this.translateY = 0;
this.pullDownStatus = 1;
}, mm || 0);
},
prevent(e) {
if(this.translateY > 0) {
e.preventDefault();
}
},
scroll(e) {
this.$emit('onScroll',e);
this.oldTop = e.detail.scrollTop;
if(this.timeout) clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
this.scrolltolower(e);
},20);
},
scrolltolower(e) {
let view = uni.createSelectorQuery().in(this).select(".you-scroll-inner");
view.fields({
size: true,
scrollOffset: true
}, data => {
if(data.scrollTop >= (e.detail.scrollHeight - data.height - this.reachBottomDistance)) {
this.$emit('onLoadMore',e);
}
}).exec();
},
isWeixinCient(){
var ua = navigator.userAgent.toLowerCase();
if(ua.match(/MicroMessenger/i)=="micromessenger") {
return true;
} else {
return false;
}
},
goTop(top) {
this.scrollToTop = this.oldTop;
this.$nextTick(function() {
this.scrollToTop = top || 0;
});
}
},
mounted() {
// #ifdef H5
if(this.isWeixinCient()) {
document.body.addEventListener('touchmove', this.prevent);
}
// #endif
},
destroyed() {
// #ifdef H5
if(this.isWeixinCient()) {
document.body.removeEventListener('touchmove', this.prevent);
}
// #endif
}
}
</script>
<style scoped>
.you-scroll {
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
// background-color: #eee;
}
.you-scroll .pullDown {
width: 100%;
height: 40px;
line-height: 50px;
text-align: center;
font-size: 14px;
overflow: hidden;
transform: translateY(-100%);
position: absolute;
top: -40px;
left: 0;
}
.you-scroll .pullDown .down-icon {
width: 40px;
height: 32px;
display: inline-block;
vertical-align: middle;
}
.you-scroll .pullDown .animate {
-webkit-animation: scaleIcon 1s infinite linear;
-moz-animation: scaleIcon 1s infinite linear;
-ms-animation: scaleIcon 1s infinite linear;
animation: scaleIcon 1s infinite linear;
}
.you-scroll .pullDown span {
white-space: nowrap;
overflow: hidden;
display: inline-block;
vertical-align: middle;
}
.you-scroll .you-scroll-inner {
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
}
.you-scroll-content {
overflow: hidden;
}
@-webkit-keyframes scaleIcon {
0% {
transform: scaleY(1);
}
40% {
transform: scaleY(0.8);
}
80% {
transform: scaleY(0.9);
}
100% {
transform: scaleY(1);
}
}
@-moz-keyframes scaleIcon {
0% {
transform: scaleY(1);
}
40% {
transform: scaleY(0.8);
}
80% {
transform: scaleY(0.9);
}
100% {
transform: scaleY(1);
}
}
@-ms-keyframes scaleIcon {
0% {
transform: scaleY(1);
}
40% {
transform: scaleY(0.8);
}
80% {
transform: scaleY(0.9);
}
100% {
transform: scaleY(1);
}
}
@keyframes scaleIcon {
0% {
transform: scaleY(1);
}
40% {
transform: scaleY(0.8);
}
80% {
transform: scaleY(0.9);
}
100% {
transform: scaleY(1);
}
}
</style>