half-screen.uvue 6.6 KB
Newer Older
DCloud-yyl's avatar
DCloud-yyl 已提交
1
<template>
DCloud-yyl's avatar
DCloud-yyl 已提交
2
	<view id="page" class="page">
W
wanganxp 已提交
3
		<text style="margin: 10px">半屏弹窗,演示了弹出层内scroll-view滚动到顶时由滚变拖。本效果是通过监听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 147
			this.halfNode = uni.getElementById('halfScreen');
			this.scrollNode = uni.getElementById('halfScroll');
DCloud-yyl's avatar
DCloud-yyl 已提交
148

149 150 151
			this.halfHeight = this.halfNode!.getBoundingClientRect().height;
			this.totalHeight = uni.getElementById('page')?.getBoundingClientRect()?.height??0;//uni.getWindowInfo().windowHeight;
			this.halfNode?.style?.setProperty('top', this.totalHeight.toFixed(2));
DCloud-yyl's avatar
DCloud-yyl 已提交
152
		},
153 154 155 156 157 158
    onResize() {
      this.halfHeight = this.halfNode?.getBoundingClientRect()?.height??0;
      this.totalHeight = uni.getElementById('page')?.getBoundingClientRect()?.height??0;
      this.halfNode?.style?.setProperty('top', this.totalHeight.toFixed(2));
      this.halfNode?.style?.setProperty('visibility','hidden');
    }
DCloud-yyl's avatar
DCloud-yyl 已提交
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
	}
</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 已提交
186
	background-color: ghostwhite;
DCloud-yyl's avatar
DCloud-yyl 已提交
187 188 189
	border-radius: 10px 10px 0 0;
}
.halfScroll {
DCloud-yyl's avatar
DCloud-yyl 已提交
190
	background-color: white;
DCloud-yyl's avatar
DCloud-yyl 已提交
191 192 193 194 195
}
.item {
	height: 100px;
}
</style>