也許有人會(huì)問,小程序中都是豎直app形態(tài),要橫豎屏判斷有什么用?即使判斷出了橫屏狀態(tài),你能把小程序橫過來(lái)?答案是不能的,但是判斷當(dāng)前設(shè)備處于橫屏或者豎屏狀態(tài)來(lái)實(shí)現(xiàn)一些友好的用戶體驗(yàn)交互方式的需求確實(shí)存在。例如手機(jī)橫屏,讓視頻播放自動(dòng)全屏,手機(jī)豎屏,讓視頻切換回來(lái)小屏。
然而,截止至目前,小程序官方的API中并沒有提供這樣的橫豎屏判斷的方法。那么我們只能自己想辦法實(shí)現(xiàn)這樣的判斷。小程序的設(shè)備API中提供了加速度計(jì)的監(jiān)聽方法,使用方法如下: wx.onAccelerometerChange(function(res) { console.log(res.x) console.log(res.y) console.log(res.z) }) 加速度計(jì)的三軸以下是一般移動(dòng)設(shè)備的加速度計(jì)三軸坐標(biāo)系示例圖: 以手機(jī)豎直面向用戶為例,加速計(jì)的三軸坐標(biāo)系統(tǒng)的X、Y、Z軸定義如下:
當(dāng)手機(jī)處于靜止?fàn)顟B(tài)時(shí),手機(jī)此時(shí)只受一個(gè)重力加速度(1g=9.8m/s²)的作用,加速度計(jì)返回的res.x、res.y、res.z的值就是設(shè)備的三軸受到的加速度的值,取值范圍從[-1g,1g]。設(shè)備以不同方式放置時(shí),x/y/z的值如下:
計(jì)算姿態(tài)角在stackoverflow上找到了根據(jù)加速度計(jì)三軸的值計(jì)算姿態(tài)角公式(https://stackoverflow.com/questions/3755059/3d-accelerometer-calculate-the-orientation),經(jīng)過結(jié)合設(shè)備的三軸坐標(biāo)方向?qū)竭M(jìn)行調(diào)整,最終得出了公式: Pitch = atan2(Y, Z) * 180/M_PI;Roll = atan2(-X, sqrt(Y*Y+ Z*Z)) * 180/M_PI;
當(dāng)設(shè)備繞著自身Y軸旋轉(zhuǎn)時(shí)(表示手機(jī)左側(cè)或右側(cè)翹起的角度),該角度值將會(huì)發(fā)生變化,取值范圍是-90到90度。
當(dāng)手機(jī)繞著自身的Y軸旋轉(zhuǎn)(表示手機(jī)頂部或尾部翹起的角度),該角度會(huì)發(fā)生變化,值的范圍是-180到180度。
接下來(lái)就是根據(jù)自己對(duì)橫豎屏角度的觀測(cè),再結(jié)合微信小程序中,視頻全屏只能以手機(jī)向左旋轉(zhuǎn)方式全屏的特性,只對(duì)用戶左側(cè)橫屏判斷為橫屏狀態(tài),實(shí)現(xiàn)代碼片段如下: // 0為豎屏,1為橫屏 let lastState = 0; let lastTime = Date.now(); wx.startAccelerometer(); wx.onAccelerometerChange((res) => { const now = Date.now(); // 500ms檢測(cè)一次 if (now - lastTime < 500) { return; } lastTime = now; let nowState; // 57.3 = 180 / Math.PI const Roll = Math.atan2(-res.x, Math.sqrt(res.y * res.y + res.z * res.z)) * 57.3; const Pitch = Math.atan2(res.y, res.z) * 57.3; // console.log('Roll: ' + Roll, 'Pitch: ' + Pitch) // 橫屏狀態(tài) if (Roll > 50) { if ((Pitch > -180 && Pitch < -60) || (Pitch > 130)) { nowState = 1; } else { nowState = lastState; } } else if ((Roll > 0 && Roll < 30) || (Roll < 0 && Roll > -30)) { let absPitch = Math.abs(Pitch); // 如果手機(jī)平躺,保持原狀態(tài)不變,40容錯(cuò)率 if ((absPitch > 140 || absPitch < 40)) { nowState = lastState; } else if (Pitch < 0) { /*收集豎向正立的情況*/ nowState = 0; } else { nowState = lastState; } } else { nowState = lastState; } // 狀態(tài)變化時(shí),觸發(fā) if (nowState !== lastState) { lastState = nowState; if (nowState === 1) { console.log('change:橫屏'); } else { console.log('change:豎屏'); } } }); 然后就可以在橫豎屏切換的狀態(tài)下,去切換視頻的橫豎屏了 if (state === 1) { video.requestFullScreen(); } else { video.exitFullScreen(); }
其他 另外,在這里發(fā)現(xiàn)小程序的一個(gè)小bug,就是當(dāng)進(jìn)入一個(gè)頁(yè)面,馬上就調(diào)用requestFullScreen()方法去拉起視頻全屏?xí)r,會(huì)破壞整個(gè)頁(yè)面的布局,并且再調(diào)用全屏方法時(shí),視頻就無(wú)法再全屏了,像這樣: 所以為了防止用戶直接以橫屏的狀態(tài)進(jìn)入一個(gè)視頻播放頁(yè),而我們的橫屏判斷檢測(cè)生效立即觸發(fā)全屏引發(fā)bug,我將監(jiān)聽橫豎屏的事件通過setTimeout(listener, 3000)延遲3s監(jiān)聽,這樣橫屏才不會(huì)觸發(fā)bug。
最后 文中的很多知識(shí)點(diǎn)很多都是從網(wǎng)絡(luò)文章學(xué)來(lái),可能存在錯(cuò)誤的理解,如有錯(cuò)誤,歡迎各位指正。 最后再打個(gè)廣告,歡迎喜歡看游戲直播的小伙伴來(lái)試用我們的《TG電競(jìng)》直播小程序,這里聚合各大平臺(tái)的知名主播,總有一款適合你哦。 |