實現效果
先上圖說明一下實現的效果碱工,如下面動圖:
前言
效果實現代碼建立在vue項目工程之上庵寞,但是具體實現原理通用茅姜,讀者可根據自身需求進行遷移闪朱。
原理簡述
1、構造一個浮動盒子钻洒,樣式代碼如下
.upglidebox { position: fixed; height: 600px; width: 100%; background-color: #fff; border-top-right-radius: 40px; border-top-left-radius: 40px;}
其中定位方式為了與原本的父容器不造成滑動上的沖突监透,需要設成fixed。
2航唆、使用HTML5觸摸事件(touchstart胀蛮、touchmove和touchend),分別用來記錄手指操作對盒子的影響糯钙。通過屏蔽系統(tǒng)本身的滑動效果粪狼,自定義實現盒子隨手指上下滑的行為。
mounted () {
? ? let distance = 0, startPageY = 0, endPageY = 0, curHeight = 0;
? ? const upglideboxDom = this.$refs['upglidebox']
? ? upglideboxDom.addEventListener('touchstart', e => {
? ? ? startPageY = e.changedTouches[0].pageY
? ? })
? ? upglideboxDom.addEventListener('touchend', e => {
? ? ? // 記錄上滑框的當前高度
? ? ? curHeight = distance;
? ? })
? ? const boxHeight = upglideboxDom.clientHeight
? ? const boxTop = parseFloat(upglideboxDom.style.top.replace('px', ''))
? ? const maxScrollheight = boxHeight - (document.documentElement.clientHeight - boxTop)
? ? // let isScrollMax = false
? ? upglideboxDom.addEventListener('touchmove', e => {
? ? ? // 屏蔽盒子默認的滑動行為
? ? ? e.preventDefault()
? ? ? endPageY = e.changedTouches[0].pageY
? ? ? distance = startPageY - endPageY + curHeight
? ? ? // 往下滑就瞬間返回初始位置
? ? ? if (distance < 0) {
? ? ? ? distance = 0
? ? ? }
? ? ? // 最多只能讓盒子滑出貼近底部
? ? ? if (distance > maxScrollheight) {
? ? ? ? distance = maxScrollheight
? ? ? }
? ? ? this.upglideboxStyle = `
? ? ? ? top:400px;
? ? ? ? transform: translateY(${-distance}px);
? ? ? `;
? ? }, { passive: false })
? }
因為瀏覽器必須要在執(zhí)行事件處理函數之后任岸,才能知道有沒有掉用過 preventDefault() 再榄,瀏覽器不能及時響應滾動,略有延遲享潜。所以為了讓頁面滾動的效果如絲般順滑困鸥,從 chrome56 開始,在 window、document 和 body 上注冊的 touchstart 和 touchmove 事件處理函數疾就,會默認為是 passive: true澜术。瀏覽器忽略 preventDefault() 就可以第一時間滾動了,其中{ passive: false }就是為了讓? e.preventDefault()起效猬腰。
后話
因為時間原因暫時記錄于此鸟废,代碼后續(xù)上傳,后續(xù)會優(yōu)化成類似豆瓣app電影評論頁面上滑框類似效果姑荷。若有更好的實現辦法盒延,煩請指教。