half-screen.uvue 6.2 KB
Newer Older
DCloud-yyl's avatar
DCloud-yyl 已提交
1
<template>
DCloud-yyl's avatar
DCloud-yyl 已提交
2
	<view id="page" class="page">
DCloud-yyl's avatar
DCloud-yyl 已提交
3
		<text>半屏弹窗效果是通过监听TouchEvent实现,当半屏窗口移动时禁用scroll-view的滚动,避免两者的冲突。</text>
DCloud-yyl's avatar
DCloud-yyl 已提交
4
		<button class="bottomButton" @click="switchHalfScreen(true)">打开弹窗</button>
DCloud-yyl's avatar
DCloud-yyl 已提交
5
		<view id="halfScreen" class="halfScreen" @touchstart="onHalfTouchStart" @touchmove="onHalfTouchMove" @touchend="onHalfTouchEnd">
DCloud-yyl's avatar
DCloud-yyl 已提交
6
			<view class="halfTitle" >半屏弹窗标题</view>
DCloud-yyl's avatar
DCloud-yyl 已提交
7
			<scroll-view id="halfScroll" class="halfScroll" @scroll="onScroll" rebound="true">
DCloud-yyl's avatar
DCloud-yyl 已提交
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
				<view v-for="(item,index) in list" :key="index" class="item">
					half screen content-{{item}}
				</view>
			</scroll-view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				list: ['1','2','3','4','5','6','7','8','9','10','11','12','13','14','15'],
				totalHeight: 0,		//总高度
				halfMove: false,	//是否Move,响应TouchMove
				halfScreenY: 0,		//响应TouchMove的起始点Y坐标
				halfOffset: 0,		//偏移的位置,translateY
				halfHeight: 0,		//高度
				lastY: 0,			//上次
				lastY2: 0,			//
				bAnimation: false,	//是否动画
DCloud-yyl's avatar
DCloud-yyl 已提交
29 30
				halfNode: null as Element | null,
				scrollNode: null as Element | null
DCloud-yyl's avatar
DCloud-yyl 已提交
31 32 33 34 35 36 37 38 39 40 41
			}
		},
		methods: {
			onHalfTouchStart(_:TouchEvent) {
				this.halfNode?.style?.setProperty('transitionDuration', 0);
				//console.log('Title TouchStart: ', e);
			},
			onHalfTouchMove(e:TouchEvent) {
				if(this.bAnimation){//容错处理
					return;
				}
DCloud-yyl's avatar
DCloud-yyl 已提交
42
				let top:number = this.scrollNode?.scrollTop??0;
DCloud-yyl's avatar
DCloud-yyl 已提交
43 44 45 46 47 48 49 50
				let p = e.touches[0];
				this.lastY2 = this.lastY;
				this.lastY = p.screenY;
				if(top <= 0.01 || this.halfMove){
					if(this.halfScreenY == 0){
						this.halfScreenY = p.screenY;
					}
					let offset = p.screenY-this.halfScreenY;
DCloud-yyl's avatar
DCloud-yyl 已提交
51
					if(offset > 0){//向下滚动
DCloud-yyl's avatar
DCloud-yyl 已提交
52
						this.halfMove = true;
DCloud-yyl's avatar
DCloud-yyl 已提交
53
            this.scrollNode?.setAttribute('scroll-y', 'false');
DCloud-yyl's avatar
DCloud-yyl 已提交
54
						this.halfNode?.style?.setProperty('transform','translateY('+offset+'px)');
DCloud-yyl's avatar
DCloud-yyl 已提交
55 56 57
            if(offset==0){
              console.log('translateY(0px)', this.halfOffset)
            }
DCloud-yyl's avatar
DCloud-yyl 已提交
58
						this.halfOffset = offset;
DCloud-yyl's avatar
DCloud-yyl 已提交
59
					}else if(this.halfOffset>0){//向上滚动
DCloud-yyl's avatar
DCloud-yyl 已提交
60 61
						offset = this.halfScreenY-p.screenY;
						if(offset>this.halfOffset){
DCloud-yyl's avatar
DCloud-yyl 已提交
62 63 64
							offset = 0;
              this.halfMove = false;
              this.scrollNode?.setAttribute('scroll-y', 'true');
DCloud-yyl's avatar
DCloud-yyl 已提交
65 66
						}
						this.halfNode?.style?.setProperty('transform','translateY('+offset+'px)');
DCloud-yyl's avatar
DCloud-yyl 已提交
67 68 69
            if(offset==0){
              console.log('translateY(0px)', this.halfOffset)
            }
DCloud-yyl's avatar
DCloud-yyl 已提交
70 71 72 73 74 75
						this.halfOffset = offset;
					}
				}
				//console.log('TouchMove', e.target);
			},
			onHalfTouchEnd(_:TouchEvent) {
DCloud-yyl's avatar
DCloud-yyl 已提交
76
        this.halfScreenY = 0;
DCloud-yyl's avatar
DCloud-yyl 已提交
77 78 79
				if(this.bAnimation){//容错处理
					return;
				}
DCloud-yyl's avatar
DCloud-yyl 已提交
80
				let top:number = this.scrollNode?.scrollTop??0;
DCloud-yyl's avatar
DCloud-yyl 已提交
81 82 83 84 85 86 87
				let bHide = (this.halfHeight-this.halfOffset)<this.halfHeight/4;
				if(bHide){
					bHide = this.lastY2>0&&this.lastY2<=this.lastY;
				}else if(top <= 0.01){
					bHide = (this.lastY-this.lastY2)>3;		//向下滑动计算加速度判断是否关闭,简单处理未考虑时间
				}
				if(bHide){
DCloud-yyl's avatar
DCloud-yyl 已提交
88
					this.switchHalfScreen(false);
DCloud-yyl's avatar
DCloud-yyl 已提交
89
				}else if(this.halfOffset>0){
DCloud-yyl's avatar
DCloud-yyl 已提交
90
					this.resumeHalfScreen();
DCloud-yyl's avatar
DCloud-yyl 已提交
91 92 93 94 95 96 97 98 99 100 101
				}
			},
			onScroll(_: ScrollEvent) {
				//console.log('onScroll: ', e);
			},
			switchHalfScreen(show:boolean) {
				if(show&&('visible'==this.halfNode?.style?.getPropertyValue('visibility'))){//容错处理
					console.log('qucik click button!!!');
					return;
				}
				this.halfMove = false;
DCloud-yyl's avatar
DCloud-yyl 已提交
102
        this.scrollNode?.setAttribute('scroll-y', 'true');
DCloud-yyl's avatar
DCloud-yyl 已提交
103 104 105 106 107 108 109 110 111 112 113 114 115 116
				this.halfScreenY = 0;
				this.halfOffset = 0;
				let top = this.totalHeight;
				let time = 300;
				if(show){
					top = this.totalHeight*30/100;	//计算显示的位置
					this.halfNode?.style?.setProperty('visibility','visible');
					this.halfNode?.style?.setProperty('transitionTimingFunction','ease-in-out');
				}else{
					this.halfNode?.style?.setProperty('transitionTimingFunction','linear');
					time *= (this.halfHeight/this.totalHeight);		//计算关闭动画时间
				}
				this.halfNode?.style?.setProperty('transitionDuration', time.toFixed(0));
				this.halfNode?.style?.setProperty('transitionProperty','top');
DCloud-yyl's avatar
DCloud-yyl 已提交
117
				this.halfNode?.style?.setProperty('top', top.toFixed(2));
DCloud-yyl's avatar
DCloud-yyl 已提交
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
				setTimeout(()=>{
					if(!show){
						this.halfNode?.style?.setProperty('visibility','hidden');
						this.halfNode?.style?.setProperty('transitionDuration', 0);
						this.halfNode?.style?.setProperty('transform','');
					}
					this.halfNode?.style?.setProperty('transitionProperty','');
					this.bAnimation = false;
				}, time)
				this.bAnimation = true;
			},
			resumeHalfScreen() {
				let time = 300;//(500*this.halfOffset/this.halfHeight).toFixed(0); //回弹动画时间
				this.halfNode?.style?.setProperty('transitionDuration',time.toFixed(0));
				this.halfNode?.style?.setProperty('transitionTimingFunction','ease-in-out');
				this.halfNode?.style?.setProperty('transitionProperty','transform');
				this.halfNode?.style?.setProperty('transform','translateY(0px)');
				this.halfMove = false;
DCloud-yyl's avatar
DCloud-yyl 已提交
136
        this.scrollNode?.setAttribute('scroll-y', 'true');
DCloud-yyl's avatar
DCloud-yyl 已提交
137 138 139 140 141 142 143 144 145
				this.halfScreenY = 0;
				this.halfOffset = 0;
				setTimeout(()=>{
					this.bAnimation = false;
				}, time)
				this.bAnimation = true;
			}
		},
		onReady() {
DCloud-yyl's avatar
DCloud-yyl 已提交
146
			this.halfNode = uni.getElementById('halfScreen');
DCloud-yyl's avatar
DCloud-yyl 已提交
147
			this.halfHeight = this.halfNode!.getBoundingClientRect().height;
DCloud-yyl's avatar
DCloud-yyl 已提交
148
			this.scrollNode = uni.getElementById('halfScroll');
DCloud-yyl's avatar
DCloud-yyl 已提交
149

DCloud-yyl's avatar
DCloud-yyl 已提交
150
			this.totalHeight = uni.getWindowInfo().windowHeight;//uni.getElementById('page')?.getBoundingClientRect()?.height??0;
DCloud-yyl's avatar
DCloud-yyl 已提交
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
			this.halfNode?.style?.setProperty('top', this.totalHeight.toString());
		},
	}
</script>

<style>
.page {
	flex: 1;
	background-color: darkgrey;
}
.bottomButton {
	position: absolute;
	width: 100%;
	bottom: 0px;
}
.halfScreen {
	position: absolute;
	top: 100%;
	width: 100%;
	height: 70%;
	transition-timing-function: ease-in-out; /*ease ease-in ease-out ease-in-out linear step-start step-end*/
	transition-property: top;
	transition-duration: 0;
	visibility: hidden;
}
.halfTitle {
	align-items: center;
	justify-content: center;
	height: 48px;
DCloud-yyl's avatar
DCloud-yyl 已提交
180
	background-color: ghostwhite;
DCloud-yyl's avatar
DCloud-yyl 已提交
181 182 183
	border-radius: 10px 10px 0 0;
}
.halfScroll {
DCloud-yyl's avatar
DCloud-yyl 已提交
184
	background-color: white;
DCloud-yyl's avatar
DCloud-yyl 已提交
185 186 187 188 189
}
.item {
	height: 100px;
}
</style>