Js 網頁全屏(vue)
效果描述
以下邏輯均正常
點擊按鈕全屏、點擊按鈕退出全屏、再點擊按鈕全屏
點擊按鈕全屏,F11 / ESC 退出全屏,點擊按鈕全屏
F11 進入全屏,點擊按鈕退出全屏
不同頁面操作全屏,切換全屏均能精准的控制按鈕顯示的是全屏 / 縮放
申明
-
本 demo 默認狀態是全屏(刷新網頁也會退出全屏,切換頁面不會)
-
只考慮網頁全屏,不考慮網頁單個元素全屏
- 項目中有彈窗全屏等,可能會有兼容bug,暫時沒有去試驗,不知道如何
-
代碼里結合了 vuex,安裝使用請參考:VueX(Vue狀態管理模式)
瀏覽器兼容效果:
(僅用公司電腦上有的幾個瀏覽器測試了一遍)
- 谷歌瀏覽器、IE11、Edge火狐、360安全瀏覽器 均能正常支持本博客的全屏方法以及全屏css
本博客起因
還是想叨叨一下為什么百度這么方便還是會有這么一篇博客,畢竟是惡心過來的
(這個方案是我寫了好幾個版本才得出的)
- 最主要的還是自己看着 bug不爽
一:全屏API各瀏覽器支持不同(主要講的是里面的方法,谷歌瀏覽器里部分兼容...)
- 我要判斷全屏木的辦法,一會兒靈一會兒不靈的
二:無法監聽 ESC、F11 退出全屏的事件(即使我已經監聽了這兩個案件事件,在退出全屏的時候,它們依舊不能被監聽到)
- 我自己記錄的全屏狀態被這兩個案件搞混亂了
解決方案
參考博客中有提到:
- 注意:要在用戶授權全屏后才能獲取全屏的元素(但我的瀏覽器好像沒有授權這么個操作,所以不管它)
解決思路
主要在 vuex 中處理全屏狀態變量 fullscreen 與真正操作瀏覽器全屏退出全屏
- vuex 中的變量很多地方都可以獲取到
- 定義一個全屏處理方法,根據當前網頁是否有全屏元素來進入或者退出全屏
在 app.vue 全局里監聽 F11 與全屏改變事件
- 等於把 F11 的進入全屏改成了自己的進入全屏
- ESC退出全屏監聽不到,也就不監聽它的按鍵了
- 通過全屏事件監聽來改變全屏狀態變量 fullscreen 的值(在 ESC、F11 退出全屏的時候也會觸發)
在 xx.vue 中給按鈕增加全屏、縮放(退出全屏)功能
- 調用 vuex 中的處理全屏方法
(也可以寫一個 lib 通用函數,將變量與函數都封裝進入,然后在合適的地方調用,全屏事件監聽放在什么位置暫時沒有想清楚(主要是不同頁面切換該如何管理這個監聽事件))
代碼實現
src\store\index.js
(vuex)
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
// 全屏變量,標識當前是否為全屏狀態
fullscreen: false,
element: document.documentElement
},
mutations: {
// 改變全屏狀態變量
changeFullscreenVar(state) {
state.fullscreen = !state.fullscreen
},
// 進入全屏
lanchFullscreen(state) {
var element = state.element
if(element.requestFullscreen) {
element.requestFullscreen()
} else if(element.mozRequestFullScreen) {
element.mozRequestFullScreen()
} else if(element.msRequestFullscreen) {
element.msRequestFullscreen()
} else if(element.webkitRequestFullscreen) {
element.webkitRequestFullScreen()
}
},
// 退出全屏
exitFullscreen(state) {
if(document.exitFullscreen) {
document.exitFullscreen()
} else if(document.mozCancelFullScreen) {
document.mozCancelFullScreen()
} else if(document.msExitFullscreen) {
document.msExiFullscreen()
} else if(document.webkitCancelFullScreen) {
document.webkitCancelFullScreen()
}
},
// 暴露給外界的處理方法,調用這個方法,自行判斷是要全屏還是退出全屏
handleFullScreen(state) {
// 注意:要在用戶授權全屏后才能獲取全屏的元素,否則 fullscreenEle為null
var fullscreenEle = fullscreenEle = document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement;
console.log(fullscreenEle, '全屏元素...')
if(fullscreenEle) {
console.log('exitFullscreen..')
this.commit('exitFullscreen')
} else {
console.log('lanchFullscreen..')
this.commit('lanchFullscreen')
}
}
},
actions: {
},
modules: {
}
})
src\App.vue
<template>
<router-view />
</template>
<script>
export default {
name: 'App',
components: {
},
mounted() {
window.addEventListener('keydown', this.myKeyEvent)
if(document.exitFullscreen) {
document.addEventListener('fullscreenchange', this.changeFullscreenVar)
} else if(document.mozCancelFullScreen) {
document.addEventListener('mozfullscreenchange', this.changeFullscreenVar)
} else if(document.msExitFullscreen) {
document.addEventListener('MSFullscreenChange', this.changeFullscreenVar)
} else if(document.webkitCancelFullScreen) {
document.addEventListener('webkitfullscreenchange', this.changeFullscreenVar)
}
},
methods: {
myKeyEvent(e) {
let key = e.keyCode
if (key === 122) {
console.log('F11')
// 阻止默認的鍵盤事件
event.returnValue = false
this.$store.commit('handleFullScreen')
}
},
changeFullscreenVar(){
this.$store.commit('changeFullscreenVar')
},
fullScreenChange(event) {
console.log(event, 'fullScreenChange event')
// 判斷一下變量是不是全屏,是全屏則代表 F11、ESC 退出了全屏,需要變量更正過來
if(this.$store.state.btnFullScreen && this.$store.state.fullscreen) {
this.$store.commit('changeFullScreenVariable')
}
},
},
beforeDestroy() {
window.removeEventListener('keydown', this.myKeyEvent)
if(document.exitFullscreen) {
document.removeEventListener('fullscreenchange', this.changeFullscreenVar)
} else if(document.mozCancelFullScreen) {
document.removeEventListener('mozfullscreenchange', this.changeFullscreenVar)
} else if(document.msExitFullscreen) {
document.removeEventListener('MSFullscreenChange', this.changeFullscreenVar)
} else if(document.webkitCancelFullScreen) {
document.removeEventListener('webkitfullscreenchange', this.changeFullscreenVar)
}
}
}
</script>
src\views\xx.vue
<template>
<div v-if="!$store.state.fullscreen" class="btn cursorPointer" @click="clickTopBtn('handleFullScreen')">
<img src="./../assets/images/quanping.png" alt="">
全屏
</div>
<div v-else class="btn cursorPointer" @click="clickTopBtn('handleFullScreen')">
<img src="./../assets/images/suofang.png" alt="">
縮放
</div>
</template>
<script>
export default {
methods: {
clickTopBtn(func) {
this.$store.commit('handleFullScreen')
}
}
}
</script>
<style>
/*重在功能邏輯代碼,樣式自己寫*/
</style>
全屏css樣式
/* 多瀏覽器兼容性寫法(親測有效) */
/* Chrome, Safari, Opera 寫法 */
:-webkit-full-screen { }
/* Firefox 寫法 */
:-moz-full-screen { }
/* IE/Edge 寫法 */
:-ms-fullscreen { }
/* 標准寫法 */
:fullscreen { }
/* 也可以通過區分全屏元素 css選擇器、瀏覽器全屏樣式 */
#fullscreenEle:fullscreen { }
在全屏狀態需要改變樣式的地方根據自己的項目寫就好了
/* :fullscreen */
:fullscreen #centerInfo,
:fullscreen #rightContent{
display: none;
}
:fullscreen .menuItem:not(:nth-last-child(1)) {
margin-right: 20px;
}
:fullscreen #navMenu{
width: unset;
border-radius: 8px;
left: 10px;
top: 10px;
}
/* :-webkit-full-screen */
:-webkit-full-screen #centerInfo,
:-webkit-full-screen #rightContent{
display: none;
}
:-webkit-full-screen .menuItem:not(:nth-last-child(1)) {
margin-right: 20px;
}
:-webkit-full-screen #navMenu{
width: unset;
border-radius: 8px;
left: 10px;
top: 10px;
}
/* :-moz-full-screen */
:-moz-full-screen #centerInfo,
:-moz-full-screen #rightContent{
display: none;
}
:-moz-full-screen .menuItem:not(:nth-last-child(1)) {
margin-right: 20px;
}
:-moz-full-screen #navMenu{
width: unset;
border-radius: 8px;
left: 10px;
top: 10px;
}
/* :-ms-fullscreen */
:-ms-fullscreen #centerInfo,
:-ms-fullscreen #rightContent{
display: none;
}
:-ms-fullscreen .menuItem:not(:nth-last-child(1)) {
margin-right: 20px;
}
:-ms-fullscreen #navMenu{
/* IE 不能用 unset,案例中改成 auto 也行 */
width: auto;
border-radius: 8px;
left: 10px;
top: 10px;
}
特別鳴謝
能得出這套個人看似完美的方案,多虧了這篇博客:HTML5 API詳解(1):fullscreen全屏模式
非常感謝~