css 實(shí)現(xiàn)劉海屏樣式兼容并支持 js 獲取劉海屏高度后動(dòng)態(tài)修改
css
:root { --safe-area-inset-top: 0px; --safe-area-inset-right: 0px; --safe-area-inset-bottom: 0px; --safe-area-inset-left: 0px; --safe-area-inset-constant-top: 0px; --safe-area-inset-constant-right: 0px; --safe-area-inset-constant-bottom: 0px; --safe-area-inset-constant-left: 0px; } @supports (top: env(safe-area-inset-top, 44px)) { :root { --safe-area-inset-top: env(safe-area-inset-top, 44px); --safe-area-inset-right: env(safe-area-inset-right, 34px); --safe-area-inset-bottom: env(safe-area-inset-bottom, 34px); --safe-area-inset-left: env(safe-area-inset-left, 34px); } } @supports (top: constant(safe-area-inset-top)) { :root { --safe-area-inset-constant-top: constant(safe-area-inset-top); --safe-area-inset-constant-right: constant(safe-area-inset-right); --safe-area-inset-constant-bottom: constant(safe-area-inset-bottom); --safe-area-inset-constant-left: constant(safe-area-inset-left); } }
首先設(shè)置 css 根屬性變量值,如果是 less,通過(guò) calc 計(jì)算出增加劉海屏高度后的值,注意 calc 計(jì)算不支持不帶單位的數(shù)字相加,會(huì)導(dǎo)致結(jié)果為 0 ,所以一定要處理不帶單位的場(chǎng)景。
由于安卓不支持 constant css 函數(shù),以及安卓 9 以下低版本系統(tǒng)不支持 env css 函數(shù),會(huì)導(dǎo)致獲取的結(jié)果為 0 從而導(dǎo)致 calc 計(jì)算結(jié)果也為 0 ,所以要在初始化寫(xiě)為 0px,則通過(guò) css @supports 來(lái)判斷支持 constant 和 env 函數(shù)的情況下再賦值劉海屏高度值。
js 通過(guò)與iOS 和安卓的接口獲取到客戶端返回的實(shí)際劉海屏的高度,當(dāng)返回的高度存在時(shí),則重新賦值 root 跟元素的變量,否則用瀏覽器默認(rèn)的。
這樣實(shí)現(xiàn)的目的是為了解決部分機(jī)型下,env 函數(shù)和 constant 函數(shù)都獲取失敗導(dǎo)致無(wú)法處理劉海屏高度的場(chǎng)景。
js vue3 代碼
import { readonly, reactive, watch, ref } from 'vue'
import { setRootProperty } from '@/common/util'
export default {
install: (app) => {
const config = reactive({})
const insets = ref({ top: 0, left: 0, bottom: 0, right: 0 })
if (window.getSafeAreaInsets && typeof window.getSafeAreaInsets === 'function') {
insets.value = window.getSafeAreaInsets() // 初始化獲取劉海屏值
}
const setConfigAreaInsets = () => {
config.areaInsets = insets.value
}
const updateInsets = (top, left, bottom, right) => {
insets.value = { top, left, bottom, right }
}
function applySafeInsets() {
if (!window.EVENTS.safeAreaInsetsChange) {
return false
}
setConfigAreaInsets()
;['top', 'right', 'bottom', 'left'].forEach(prop => {
setRootProperty(`--safe-area-inset-${prop}`, `${insets.value[prop]}px`)
setRootProperty(`--safe-area-inset-constant-${prop}`, `${insets.value[prop]}px`)
})
}
watch(insets, (val) => {
applySafeInsets()
})
app.mixin({
mounted() {
applySafeInsets()
if (this === this.$root) {
window.mraid.addEventListener('safeAreaInsetsChange', updateInsets)
}
},
beforeUnmount() {
if (this === this.$root) {
window.mraid.removeEventListener('safeAreaInsetsChange', updateInsets)
}
}
})
app.config.globalProperties.$config = config
app.provide('config', readonly(config))
}
}

浙公網(wǎng)安備 33010602011771號(hào)