小程序横屏方案对比

前言

随着小程序api开放的功能日渐增多,小程序能够作到的功能和展示形式也愈来愈多,其中横屏的展示形式就是其中的一种,而实现横屏的方案也有多种,可是每种方案都有必定的缺陷,恰巧最近也在横屏方案上踩了很多坑,接下来就来和你们分享一下小程序的不一样横屏方案的优劣(踩坑心得)css

组件自带横屏方法

小程序中的媒体组件通常都会提供全屏的方法,并且全屏方法中会提供一个direction的全屏参数,能够经过这全屏参数将小程序旋转90度横屏展现,这是小程序中最简单的横屏方法。html

这个方法优势在于调用的组件全屏方法作的横屏,不须要考虑头部导航栏的胶囊按钮的显示问题,媒体组件在作全屏显示时,胶囊按钮会自动隐藏不见,同时大多数媒体组件都已经支持了同层渲染,能够经过z-index调整组件层级,所以用此法在横屏布局时能够在媒体组件上覆盖其余组件布局json

缺点:这个方法的缺点也很明显,就是只能使用媒体相关组件才能有横屏的全屏,场景很单一,若是不是媒体组件或者不想全屏,那么对不起,此法不可用小程序

计算加速度判断横屏

这个方法是以前有人发在微信社区里的一个方法,经过小程序提供的wx.onAccelerometerChange方法监听设备在x、y、z轴上的加速度,经过返回的重力加速度计算设备的旋转角度,下面贴出代码给你们参考:api

// 0为竖屏,1为横屏
  let lastState = 0;
  let lastTime = Date.now();
 
  wx.startAccelerometer();
 
  wx.onAccelerometerChange((res) => {
    const now = Date.now();
     
    // 500ms检测一次
    if (now - lastTime < 500) {
      return;
    }
    lastTime = now;
 
    let nowState;
 
    // 57.3 = 180 / Math.PI
    const Roll = Math.atan2(-res.x, Math.sqrt(res.y * res.y + res.z * res.z)) * 57.3;
    const Pitch = Math.atan2(res.y, res.z) * 57.3;
 
    // console.log('Roll: ' + Roll, 'Pitch: ' + Pitch)
 
    // 横屏状态
    if (Roll > 50) {
      if ((Pitch > -180 && Pitch < -60) || (Pitch > 130)) {
        nowState = 1;
      }else {
        nowState = lastState;
      }
 
    }else if ((Roll > 0 && Roll < 30) || (Roll < 0 && Roll > -30)) {
      let absPitch = Math.abs(Pitch);
 
      // 若是手机平躺,保持原状态不变,40容错率
      if ((absPitch > 140 || absPitch < 40)) {
        nowState = lastState;
      }else if (Pitch < 0) {/*收集竖向正立的状况*/
        nowState = 0;
      }else {
        nowState = lastState;
      }
    }
    else {
      nowState = lastState;
    }
 
    // 状态变化时,触发
    if (nowState !== lastState) {
      lastState = nowState;
      if (nowState === 1) {
        console.log('change:横屏');
      }else {
        console.log('change:竖屏');
      }
    }
  });

更多的实现细节能够前往社区帖子查看,这个方法我的实际尝试过,确实能够判断设备处在横屏仍是竖屏微信

优势:这个方法的优势在于能够监听到设备的横竖屏状况,而后根据项目须要展现不一样横竖屏布局,自由度很高布局

缺点:这个方法的缺点在于在页面内容横屏时没法使头部导航栏的胶囊按钮横屏展现,由于头部导航栏的胶囊按钮始终是固定屏幕右上角不动的,这样会使得横屏效果有点奇怪,横屏是导航栏固定在左边是竖屏时的布局,除非横屏的布局是媒体组件的全屏,这样就能遮住胶囊按钮,本身自定义一个头部导航,这样就不会显得布局奇怪学习

pageOrientation

pageOrientation是小程序提供的配置属性,能够设置当前页面是横屏展现、竖屏展现、或者自动旋转,同时提供一个onResize的监听方法,当屏幕发生旋转时会触发onResize的回调,而且会在回调中返回当前是横屏仍是竖屏以及相应区域的大小。spa

优势:配置便可,手机旋转触发监听事件,返回屏幕旋转后的宽高和当前横竖屏状况,横屏时胶囊按钮会自动旋转,这样页面布局就不会有上一个方法所说起的怪异布局设计

缺点:

  • 因为是配置形式,没办法主动调用,只能被动监听
  • 当用户将手机容许旋转关闭后,onResize的监听方法就不会触发
  • 因为小程序大多数时候使用的是rpx的单位,是一个基于响应区域大小的动态计算的单位,当屏幕发生旋转后,假设竖屏旋转到横屏,竖屏时响应区域为375 667,到了横屏时响应区域为667 375,此时onResize回调还没触发,此时的页面布局是竖屏的布局,可是因为响应区域发生变化375 667到667 375,rpx就会从新计算,此时页面的布局会忽然变大,而后onResize回调触发后才会变为横屏布局,会有布局闪现错乱的状况
  • width:100%或者width:100vw这类的占满所有的样式也会出现问题,一样假设从竖屏切换到横屏,当竖屏切换的横屏时,此时width:100%的样式,计算100%的宽度仍是竖屏时的375,不会当即切换到横屏时的667,所以切换到横屏时的一瞬间,能看到原来100%的样式,此时并无占满100%,闪了一下375以后,而后才会占满,假设咱们自定义的顶部标题栏,用了width:100%,那么我横屏时就会发现,标题栏宽度只有一半,而后才会占满

横屏时响应区域变化产生布局变化的解决办法

这个解决办法只能解决横屏时因为响应区域变化致使rpx从新的计算渲染的问题,既然rpx会在响应区域变化时从新计算渲染,那咱们最直接粗暴简单的方法就是不使用动态计算的单位px,这样就不会在横屏时从新渲染计算,可是这样也有一个问题,就是在不一样屏幕的大小的手机下也无法动态计算了

那有没有其余的更好办法呢?vmax、vmin这两个单位应该平时用的很少,我的也不多用,若是不是此次写小程序横屏,也不会关注到它

vmin:取值是当前vw和vh中较小的值,vmax:取值是当前vw和vh中较大的值

在竖屏时100vmin=375px,到了横屏时100vmin=375px,这样就能保证在横竖屏切换的时候内容大小不变,在小程序中使用calc(vmin/7.5),假设大小为10px,那么css为calc(10vmin/7.5),若是你嫌这么写麻烦,同时使用的是vs code,那么能够建立一个全局User Snippets:

"rpx to vmin" : {
  "prefix": "tovmin",
  "body": ["calc($0vmin / 7.5)"],
  "description": "rpx to vmin"
 }

这样在写css时直接写tomin就会将calc($0vmin / 7.5)输出

官方snippets建立步骤

总结

小程序中的横屏方案老是有这样或者那样的问题,并无完美的解决方案,有时仍是小程序自身缘由致使的,咱们能作的只是寻找解决办法或者换个交互设计,这篇文章的目的就是但愿对你们在作横屏方案时提供一点帮助,少踩坑,这是个人踩坑经历,提供给你们借鉴,同时也有个人一些解决办法,若是你们有更好的方案,能够一块儿学习。

若是有错误或不严谨的地方,欢迎批评指正,若是喜欢,欢迎点赞

相关文章
相关标签/搜索