Files
shanxia2.0/miniprogram/utils/safeArea.js
T

90 lines
2.6 KiB
JavaScript

import { buildSafeAreaCssVarsStyle } from './safeAreaCss.js'
export { buildSafeAreaCssVarsStyle }
const DEFAULT_NAV_CONTENT_HEIGHT = 44
const DEFAULT_GAP = 8
const DEFAULT_HORIZONTAL_PADDING = 8
function getSystemInfo() {
try {
return uni.getSystemInfoSync() || {}
} catch (error) {
return {}
}
}
function getMenuButtonRect() {
try {
const rect = uni.getMenuButtonBoundingClientRect?.()
return rect && rect.width ? rect : null
} catch (error) {
return null
}
}
export function computeSafeAreaMetrics() {
const systemInfo = getSystemInfo()
const menuRect = getMenuButtonRect()
const statusBarHeight = Number(systemInfo.statusBarHeight || 20)
const windowWidth = Number(systemInfo.windowWidth || 375)
let navContentHeight = DEFAULT_NAV_CONTENT_HEIGHT
let navTopGap = DEFAULT_GAP
let capsuleWidth = 0
let capsuleRightSafeWidth = 0
if (menuRect) {
navTopGap = Math.max(Number(menuRect.top || 0) - statusBarHeight, DEFAULT_GAP)
navContentHeight = Math.max(Number(menuRect.height || 0) + navTopGap * 2, DEFAULT_NAV_CONTENT_HEIGHT)
capsuleWidth = Number(menuRect.width || 0)
const rightInset = Math.max(windowWidth - Number(menuRect.right || windowWidth), 0)
capsuleRightSafeWidth = Math.max(capsuleWidth + rightInset + DEFAULT_HORIZONTAL_PADDING, 96)
} else {
// 无胶囊位(H5、无自定义导航栏等):不预留右侧占位;样式里已有 32rpx 水平内边距
capsuleRightSafeWidth = 0
}
const topSafeHeight = statusBarHeight
const headerHeight = topSafeHeight + navContentHeight
return {
statusBarHeight,
topSafeHeight,
navContentHeight,
headerHeight,
navTopGap,
capsuleWidth,
capsuleRightSafeWidth,
}
}
export function applySafeAreaCssVars(metrics) {
if (typeof document === 'undefined' || !document?.documentElement) return
const root = document.documentElement.style
const style = buildSafeAreaCssVarsStyle(metrics)
Object.entries(style).forEach(([key, value]) => {
root.setProperty(key, value)
})
}
export function initGlobalSafeArea() {
const metrics = computeSafeAreaMetrics()
const app = getApp?.()
if (app) {
app.globalData = app.globalData || {}
app.globalData.safeArea = metrics
}
applySafeAreaCssVars(metrics)
return metrics
}
export function getGlobalSafeArea() {
const app = getApp?.()
return app?.globalData?.safeArea || computeSafeAreaMetrics()
}
export function getSafeAreaStyle() {
return buildSafeAreaCssVarsStyle(getGlobalSafeArea())
}