微信小程序中安全区域计算和适配

文章介绍了自从iPhoneX取消Home键后,前端开发面临的安全区域适配问题,提出了三种解决方案:基于固定高度34px适配,使用苹果推荐的CSS函数env()和constant(),以及利用微信APIwx.getSystemInfo()获取安全区域信息进行适配。并提供了相应的代码示例。

前言

自从iphoneX问世之后,因为iphoneX、iphoneXR和后续全面屏手机设备,因为物理Home键被底部小黑条代替了,这时候很多前端小伙伴在开发的过程都会遇到 “全面屏”和“非全面屏”的兼容性问题,普遍问题就是底部按钮或者选项卡与底部黑线重叠

解释

根据官方解释:

安全区域指的是一个可视窗口范围,处于安全区域的内容不受圆角(corners)、齐刘海(sensor housing)、小黑条(Home Indicator)的影响。

具体区域如图展示

适配方案

当前有效的解决方式有几种

  1. 使用已知底部小黑条高度34px/68rpx来适配

  1. 使用苹果官方推出的css函数env()、constant()适配

  1. 使用微信官方API,getSystemInfo()中的safeArea对象进行适配

使用已知底部小黑条高度34px/68rpx来适配

这种方式是根据实践得出,通过物理方式测出iPhone底部的小黑条(Home Indicator)高度是34px,实际在开发者工具选中真机获取到高度也是34px,所以直接根据该值,设置margin-bottom、padding-bottom、height也能实现。同时这样做要有一个前提,需要判断当前机型是需要适配安全区域的机型。

但是这种方案相对来说是不推荐使用的。比较是一个比较古老原始的方案

使用苹果官方推出的css函数env()、constant()适配

这种方案是苹果官方推荐使用env(),constant()来适配,开发者不需要管数值具体是多少。

env和constant是IOS11新增特性,有4个预定义变量:

  • safe-area-inset-left:安全区域距离左边边界的距离

  • safe-area-inset-right:安全区域距离右边边界的距离

  • safe-area-inset-top:安全区域距离顶部边界的距离

  • safe-area-inset-bottom :安全距离底部边界的距离

具体用法如下:

Tips: constant和env不能调换位置
	padding-bottom: constant(safe-area-inset-bottom); /*兼容 IOS<11.2*/
	padding-bottom: env(safe-area-inset-bottom); /*兼容 IOS>11.2*/

其实利用这个能解决大部分的适配场景了,但是有时候开发需要自定义头部信息,这时候就没办法使用css来解决了

使用微信官方API,getSystemInfo()中的safeArea对象进行适配

通过 wx.getSystemInfo获取到各种安全区域信息,解析出具体的设备类型,通过设备类型做宽高自适应,话不多说,直接上代码

代码实现
const res = wx.getSystemInfoSync()
   const result = {
    ...res,
    bottomSafeHeight: 0,
        isIphoneX: false,
        isMi: false,
        isIphone: false,
        isIpad: false,
        isIOS: false,
        isHeightPhone: false,
  }
  const modelmes = result.model
    const system = result.system
    // 判断设备型号
    if (modelmes.search('iPhone X') != -1 || modelmes.search('iPhone 11') != -1) {
      result.isIphoneX = true;
    }
    if (modelmes.search('MI') != -1) {
      result.isMi = true;
    }
    if (modelmes.search('iPhone') != -1) {
      result.isIphone = true;
    }
    if (modelmes.search('iPad') > -1) {
      result.isIpad = true;
    }
    let screenWidth = result.screenWidth
    let screenHeight = result.screenHeight
    // 宽高比自适应
    screenWidth = Math.min(screenWidth, screenHeight)
    screenHeight = Math.max(screenWidth, screenHeight)
    const ipadDiff = Math.abs(screenHeight / screenWidth - 1.33333)
    if (ipadDiff < 0.01) {
      result.isIpad = true
    }
    if (result.isIphone || system.indexOf('iOS') > -1) {
      result.isIOS = true
    }
    const myCanvasWidth = (640 / 375) * result.screenWidth
    const myCanvasHeight = (1000 / 667) * result.screenHeight
    const scale = myCanvasWidth / myCanvasHeight
    if (scale < 0.64) {
      result.isHeightPhone = true
    }
    result.navHeight = result.statusBarHeight + 46
    result.pageWidth = result.windowWidth
    result.pageHeight = result.windowHeight - result.navHeight
    if (!result.isIOS) {
      result.bottomSafeHeight = 0
    }
   const capsuleInfo = wx.getMenuButtonBoundingClientRect()
    // 胶囊热区 = 胶囊和状态栏之间的留白 * 2 (保持胶囊和状态栏上下留白一致) * 2(设计上为了更好看) + 胶囊高度
    const navbarHeight = (capsuleInfo.top - result.statusBarHeight) * 4 + capsuleInfo.height
    // 写入胶囊数据
    result.capsuleInfo = capsuleInfo;
    // 安全区域
    const safeArea = result.safeArea
    // 可视区域高度 - 适配横竖屏场景
    const screenHeight = Math.max(result.screenHeight, result.screenWidth)
    const height = Math.max(safeArea.height, safeArea.width)
    // 状态栏高度
    const statusBarHeight = result.statusBarHeight
    // 获取底部安全区域高度(全面屏手机)
    if (safeArea && height && screenHeight) {
      result.bottomSafeHeight = screenHeight - height - statusBarHeight
      if (result.bottomSafeHeight < 0) {
        result.bottomSafeHeight = 0
      }
    }
    // 设置header高度
    result.headerHeight = statusBarHeight + navbarHeight
    // 导航栏高度
    result.navbarHeight = navbarHeight

<think>首先,用户的问题是关于微信小程序的:他们想计算微信小程序的可视区域。用户指定了“可视区域”,我需要参考提供的引用内容。 引用[1]讨论了监听标签是否在可视区域,使用了IntersectionObserver API。引用[2]讨论了“安全区域”,包括系统组件如状态栏、导航栏等,并提供了wx.getSystemInfo来获取安全区域的信息。 用户的问题是如何计算可视区域。在微信小程序中,“可视区域”可能指的是用户屏幕上可见的部分,考虑到安全区域。引用[2]提到安全区域是未被系统组件遮挡的区域,所以可视区域可能就是指安全区域。 从引用[1],可视区域可以通过IntersectionObserver来监听元素是否在可视区域内,但用户想计算可视区域本身,而不是监听元素。 引用[2]提供了wx.getSystemInfo,它返回一个safeArea对象,包含安全区域的边界(top, bottom, left, right, width, height)。这似乎是计算可视区域的关键。 用户说“我想计算微信小程序的可视区域”,所以我应该解释如何获取这个区域。 步骤: 1. **理解可视区域**:在微信小程序中,可视区域通常指的是安全区域,即未被系统组件遮挡的区域。这包括状态栏、导航栏、刘海屏等的适配。 2. **获取安全区域**:使用wx.getSystemInfo API,它返回系统信息,其中包含safeArea对象。 - 如引用[2]所示:wx.getSystemInfo({ success: function(res) { console.log(res.safeArea); } }); - safeArea对象有left, right, top, bottom, width, height属性,定义了安全区域的边界。 3. **计算可视区域**:一旦获取了safeArea,可视区域就是由这些边界定义的矩形。例如,可视区域的宽度是safeArea.width,高度是safeArea.height。 4. **其他考虑**:引用[1]提到IntersectionObserver,但那是用于监听元素是否在可视区域内,而不是计算可视区域本身。所以,对于计算可视区域,wx.getSystemInfo是主要方法。 5. **代码示例**:我应该提供一个简单的代码示例来展示如何获取计算可视区域。 6. **结构回答**:根据系统指令,回答要清晰,使用中文,并生成相关问题。同时,确保LaTeX格式正确,但在这个上下文中,可能不需要数学表达式,除非涉及计算。 - 用户提到“计算”,但主要是获取区域信息,所以可能不需要复杂数学。如果有计算,使用$...$格式。 7. **生成相关问题**:在最后,添加相关问题,如指令所示。 8. **引用**:在回答中,如果引用内容,添加引用标识。引用[1][2]是提供的,所以我应该基于它们回答。 - 例如,提到安全区域时,添加[^2]。 现在,构建回答结构: - **介绍**:解释什么是可视区域,并参考安全区域。 - **方法**:描述如何使用wx.getSystemInfo获取安全区域。 - **代码示例**:提供一个简单的代码片段。 - **注意事项**:如果有任何额外点,比如不同设备的适配。 - **相关问题**:在最后添加相关问题。 代码示例使用wx.getSystemInfo: ```javascript wx.getSystemInfo({ success: function(res) { const safeArea = res.safeArea; console.log('可视区域宽度:', safeArea.width); console.log('可视区域高度:', safeArea.height); console.log('可视区域边界:', safeArea); } }); ``` 可视区域的计算safeArea.width safeArea.height 直接给出可视区域的尺寸。 如果用户想计算特定元素是否在可视区域内,那需要使用IntersectionObserver,但用户的问题是关于计算可视区域本身,所以 focus on wx.getSystemInfo. 生成相关问题: 基于主题,如: 1. 如何监听元素是否在可视区域内? 2. 如何处理不同设备的安全区域适配? 3. 微信小程序中的其他布局API? 确保回答真实可靠,基于微信小程序官方文档。</think>### 微信小程序可视区域的计算方法 在微信小程序开发中,“可视区域”通常指用户屏幕上可见且未被系统组件(如状态栏、导航栏、刘海屏等)遮挡的区域,也称为“安全区域”。这是适配不同设备(尤其是异形屏)的关键。计算可视区域主要通过微信小程序提供的 API 实现,核心方法是获取系统信息中的 `safeArea` 对象。以下是详细步骤示例: #### 1. **理解可视区域安全区域** - **可视区域**:指小程序页面中用户实际可见的矩形区域,其尺寸位置受设备屏幕系统组件影响。 - **安全区域**:微信小程序官方定义的未被遮挡的区域,通过 `wx.getSystemInfo` 返回的 `safeArea` 对象描述,包含以下属性: - `top`:安全区域上边界(单位:px)。 - `bottom`:安全区域下边界(单位:px)。 - `left`:安全区域左边界(单位:px)。 - `right`:安全区域右边界(单位:px)。 - `width`:安全区域宽度(单位:px),计算公式为 $width = right - left$。 - `height`:安全区域高度(单位:px),计算公式为 $height = bottom - top$。 - 安全区域定义了可视区域的精确边界,开发者可直接基于此计算[^2]。 #### 2. **计算可视区域的核心方法** 使用 `wx.getSystemInfo` API 获取系统信息,并从中提取 `safeArea` 对象。以下是完整步骤: - **调用 API**:异步获取系统信息。 - **处理返回数据**:从 `res.safeArea` 中读取可视区域的边界尺寸。 - **计算公式**: - 可视区域宽度:$width = \text{safeArea.right} - \text{safeArea.left}$。 - 可视区域高度:$height = \text{safeArea.bottom} - \text{safeArea.top}$。 - 可视区域面积:$area = width \times height$(单位为 px²)。 示例代码: ```javascript // 在页面或组件的 JS 文件中调用 wx.getSystemInfo({ success: function(res) { const safeArea = res.safeArea; // 获取安全区域对象 const width = safeArea.width; // 可视区域宽度 const height = safeArea.height; // 可视区域高度 const area = width * height; // 可视区域面积 console.log('可视区域边界:', safeArea); console.log('可视区域宽度:', width, 'px'); console.log('可视区域高度:', height, 'px'); console.log('可视区域面积:', area, 'px²'); }, fail: function(err) { console.error('获取系统信息失败:', err); } }); ``` - **输出示例**:在 iPhone X 上,可能返回: ``` safeArea: { top: 44, bottom: 736, left: 0, right: 414, width: 414, height: 692 } 可视区域宽度: 414 px 可视区域高度: 692 px 可视区域面积: 286488 px² ``` - **注意事项**: - 此方法适用于所有页面组件,无需额外监听。 - 安全区域已自动适配不同设备(如安卓状态栏、iPhone 刘海屏),无需手动计算偏移量[^2]。 - 若需实时响应屏幕旋转或尺寸变化,可在 `onResize` 生命周期中重新调用此 API。 #### 3. **其他相关方法** - **监听元素是否在可视区域内**:如果目标是检测特定元素(如滚动列表中的项)是否进入可视区域,可使用 `IntersectionObserver`(参考引用[1])。但这用于元素级监听,而非计算整体可视区域。 ```javascript // 示例:监听元素是否在可视区域 const observer = wx.createIntersectionObserver(this); observer.relativeToViewport().observe('.myElement', (res) => { if (res.intersectionRatio > 0) { console.log('元素在可视区域内'); } else { console.log('元素不在可视区域内'); } }); ``` - **CSS 安全区域适配**:在小程序 WXSS 中,可使用 `env(safe-area-inset-top)` 等变量直接设置样式,避免手动计算,例如: ```css /* 确保内容在安全区域内 */ .content { padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom); } ``` #### 4. **最佳实践** - **性能考虑**:`wx.getSystemInfo` 是同步 API,调用开销小,适合在页面 `onLoad` 或组件 `attached` 时执行。 - **设备兼容性**:所有支持微信小程序的设备均提供 `safeArea` 数据,无需额外处理兼容问题。 - **实际应用**:计算可视区域常用于响应式布局,例如动态调整画布大小或避免内容被遮挡。 通过以上方法,您可以准确计算微信小程序的可见区域,确保用户体验一致可靠[^2]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值