微信小程序吸底区域适配iPhoneX的实现

所属分类: 网络编程 / JavaScript 阅读数: 241
收藏 0 赞 0 分享

微信小程序适配iPhone X主要针对fix定位到底部的区域,比如详情页或购物车底部的按钮栏,会与iPhone X的Home Indicator横条重叠,这样在点击下方按钮时很容易误触发手势操作,如下图:

旧方法

1. 获取设备信息

/**
 * 获取设备信息
 * @returns {Promise<any>}
 */
export function wechatGetSystemInfo () {
 return new Promise((resolve, reject) => {
  wx.getSystemInfo({
   success: (res) => {
    resolve(res)
   }, fail: (err) => {
    reject(err)
   }
  })
 })
}

2. 设置css样式

.view-fix-iphonex {
 bottom: ~'68rpx' !important;
}

.view-fix-iphonex::after {
 content: ' ';
 position: fixed;
 bottom: 0 !important;
 height: ~'68rpx' !important;
 width: 100%;
 background: #fff;
}

3. 设置一个标识符isIpx存在vuex中,在小程序初始化完成时判断

App.vue 中处理

<script>
 import wx from 'wx'
 import { mapGetters, mapActions } from 'vuex'
 import { wechatGetSystemInfo } from './utils/weappUtils'

 export default {
  onLaunch () {
   this.isIphoneX()
  },
  computed: {
   ...mapGetters(['isIpx'])
  },
  methods: {
   //判断设备是否是iphoneX
   isIphoneX() {
    wechatGetSystemInfo().then(res => {
     const deviceModel = 'iPhone X'
     let isIpx = false
     if (res.model.indexOf(deviceModel) > -1) {
      isIpx = true
     }
     if (this.isIpx !== isIpx) {
      this.setIsIpx(isIpx)
     }
    }).catch(err => {})
   },
   ...mapActions(['setIsIpx'])
  }
 }
</script>

4. 在需要适配的页面中设置

如在 demo.vue 中处理

<template>
   <div class="fix-view"
     :class="isIpx?'view-fix-iphonex':''"
  >
   吸附在底部的区域
  </div>
</template>


<script>
 import wx from 'wx'
 import {mapGetters} from 'vuex'

 export default {
  computed: {
   ...mapGetters(['isIpx'])
  },
 }
</script>

<style lang="less">
  .fix-view {
   position: fixed;
   left: 0;
   right: 0;
   bottom: 0;
   height: ~'100rpx';
   line-height: ~'100rpx';
   box-sizing: border-box;
   text-align: right;
   display: flex;
   justify-content: end;
   background: #fff;
  }
</style>

新方法

env() 和 constant()

iOS11 新增特性,Webkit 的一个 CSS 函数,用于设定安全区域与边界的距离,有四个预定义的变量:

  • safe-area-inset-left:安全区域距离左边边界距离
  • safe-area-inset-right:安全区域距离右边边界距离
  • safe-area-inset-top:安全区域距离顶部边界距离
  • safe-area-inset-bottom:安全区域距离底部边界距离

这里我们只需要关注 safe-area-inset-bottom 这个变量,因为它对应的就是小黑条的高度(横竖屏时值不一样)。

注意:当 viewport-fit=contain 时 env() 是不起作用的,必须要配合 viewport-fit=cover 使用。对于不支持env() 的浏览器,浏览器将会忽略它。

在这之前,笔者使用的是 constant(),后来,官方文档加了这么一段注释(坑):

The env() function shipped in iOS 11 with the name constant(). Beginning with Safari Technology Preview 41 and the iOS 11.2 beta, constant() has been removed and replaced with env(). You can use the CSS fallback mechanism to support both versions, if necessary, but should prefer env() going forward.

这就意味着,之前使用的 constant() 在 iOS11.2 之后就不能使用的,但我们还是需要做向后兼容,像这样:

padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS < 11.2 */
padding-bottom: env(safe-area-inset-bottom); /* 兼容 iOS >= 11.2 */

注意:env() 跟 constant() 需要同时存在,而且顺序不能换。

更详细说明,参考文档:Designing Websites for iPhone X

如何适配

了解了以上所说的几个知识点,接下来我们适配的思路就很清晰了。

第一步:设置网页在可视窗口的布局方式

新增 viweport-fit 属性,使得页面内容完全覆盖整个窗口:

<meta name="viewport" content="width=device-width, viewport-fit=cover">

前面也有提到过,只有设置了 viewport-fit=cover,才能使用 env()。

第二步:页面主体内容限定在安全区域内

这一步根据实际页面场景选择,如果不设置这个值,可能存在小黑条遮挡页面最底部内容的情况。

body { 
	padding-bottom: constant(safe-area-inset-bottom);
  padding-bottom: env(safe-area-inset-bottom);
}

第三步:fixed 元素的适配类型一:fixed 完全吸底元素(bottom = 0),比如下图这两种情况:

可以通过加内边距 padding 扩展高度:

{ 
	padding-bottom: constant(safe-area-inset-bottom);
  padding-bottom: env(safe-area-inset-bottom);
}

或者通过计算函数 calc 覆盖原来高度:

{ 
	height: calc(60px(假设值) + constant(safe-area-inset-bottom));
  height: calc(60px(假设值) + env(safe-area-inset-bottom));
}

注意,这个方案需要吸底条必须是有背景色的,因为扩展的部分背景是跟随外容器的,否则出现镂空情况。

还有一种方案就是,可以通过新增一个新的元素(空的颜色块,主要用于小黑条高度的占位),然后吸底元素可以不改变高度只需要调整位置,像这样:

{ 
	margin-bottom: constant(safe-area-inset-bottom);
  margin-bottom: env(safe-area-inset-bottom);
}

空的颜色块:

{ 
	position: fixed;
  bottom: 0;
  width: 100%;
  height: constant(safe-area-inset-bottom);
  height: env(safe-area-inset-bottom);
  background-color: #fff;
}

类型二:fixed 非完全吸底元素(bottom ≠ 0),比如 “返回顶部”、“侧边广告” 等

像这种只是位置需要对应向上调整,可以仅通过外边距 margin 来处理:

{ 
	margin-bottom: constant(safe-area-inset-bottom);
  margin-bottom: env(safe-area-inset-bottom);
}

或者,你也可以通过计算函数 calc 覆盖原来 bottom 值:

{ 
	bottom: calc(50px(假设值) + constant(safe-area-inset-bottom));
  bottom: calc(50px(假设值) + env(safe-area-inset-bottom));
}

你也可以使用 @supports 隔离兼容样式

写到这里,我们常见的两种类型的 fixed 元素适配方案已经了解了吧。如果我们只希望 iPhoneX 才需要新增适配样式,我们可以配合 @supports 来隔离兼容样式,当然这个处理对页面展示实际不会有任何影响:

@supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) { 
	div {
  	margin-bottom: constant(safe-area-inset-bottom);
    margin-bottom: env(safe-area-inset-bottom); 
  }
}
更多精彩内容其他人还在看

简单的实现点击箭头图片切换的js代码

这个是一个简单的点击箭头图片切换的例子。JS部分采用过的是jQuery
收藏 0 赞 0 分享

很弱的js表格换行效果(表格移动行)

很弱的js表格换行效果(表格移动行),可以将表格的一行向上或向下移动,主要是学习dom之表格控制操作
收藏 0 赞 0 分享

始终在页面底部的层js实现代码

其实就是通过js将层始终定位在底部,多用于提示效果
收藏 0 赞 0 分享

JavaScript 模式之工厂模式(Factory)应用介绍

工厂模式也是对象创建模式之一,它通常在类或类的静态方法中去实现,本文将详细介绍JavaScript 工厂模式
收藏 0 赞 0 分享

中国地区三级联动下拉菜单效果分析

主要的数据和功能实现都是在js文件中,网上找的地区数据有的地方不完整,需要自己添加,本文将详细介绍
收藏 0 赞 0 分享

javascript 图片裁剪技巧解读

本文将提供php版的JavaScript裁剪图片代码,仅供大家参考
收藏 0 赞 0 分享

jquery getScript动态加载JS方法改进详解

有许多朋友需要使用getScript方法动态加载JS,本文将详细介绍此功能的实现方法
收藏 0 赞 0 分享

基于JQuery模仿苹果桌面的Dock效果(初级版)

新的一天新的开始,今天要分享的是用JQuery模仿苹果操作系统桌面的Dock效果,之所以称之为初级版,是因为其中还有一些bug,显示效果并不稳定
收藏 0 赞 0 分享

基于JQuery的模拟苹果桌面Dock效果(稳定版)

之所以将它命名为稳定版,是因为之前已经分享了一个初级版本的,之前的初级版中存在很多bug。现在经过反复琢磨、实验,修复了之前版本存在的很多不足之处,就算鼠标快速的滑动依然表现的很稳定
收藏 0 赞 0 分享

JavaScript 用cloneNode方法克隆节点的代码

很多时候我们需要通过HTML DOM 的方式,用JavaScript 动态生成很多相同的节点,包括其子节点
收藏 0 赞 0 分享
查看更多