(编辑:jimmy 日期: 2024/12/27 浏览:2)
前言
随着小程序api开放的功能日渐增多,小程序可以做到的功能和展现形式也越来越多,其中横屏的展现形式就是其中的一种,而实现横屏的方案也有多种,但是每种方案都有一定的缺陷,恰巧最近也在横屏方案上踩了不少坑,接下来就来和大家分享一下小程序的不同横屏方案的优劣(踩坑心得)
组件自带横屏方法
小程序中的媒体组件一般都会提供全屏的方法,而且全屏方法中会提供一个direction的全屏参数,可以通过这全屏参数将小程序旋转90度横屏展示,这是小程序中最简单的横屏方法。
这个方法优点在于调用的组件全屏方法做的横屏,不需要考虑头部导航栏的胶囊按钮的显示问题,媒体组件在做全屏显示时,胶囊按钮会自动隐藏不见,同时大多数媒体组件都已经支持了同层渲染,可以通过z-index调整组件层级,因此用此法在横屏布局时可以在媒体组件上覆盖其他组件布局
缺点:这个方法的缺点也很明显,就是只能使用媒体相关组件才能有横屏的全屏,场景很单一,如果不是媒体组件或者不想全屏,那么对不起,此法不可用
计算加速度判断横屏
这个方法是之前有人发在微信社区里的一个方法,通过小程序提供的wx.onAccelerometerChange方法监听设备在x、y、z轴上的加速度,通过返回的重力加速度计算设备的旋转角度,下面贴出代码给大家参考:
// 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的回调,并且会在回调中返回当前是横屏还是竖屏以及相应区域的大小。
优点:配置即可,手机旋转触发监听事件,返回屏幕旋转后的宽高和当前横竖屏情况,横屏时胶囊按钮会自动旋转,这样页面布局就不会有上一个方法所提及的怪异布局
缺点:
横屏时响应区域变化产生布局变化的解决办法
这个解决办法只能解决横屏时由于响应区域变化导致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创建步骤
总结
小程序中的横屏方案总是有这样或者那样的问题,并没有完美的解决方案,有时还是小程序自身原因导致的,我们能做的只是寻找解决办法或者换个交互设计,这篇文章的目的就是希望对大家在做横屏方案时提供一点帮助,少踩坑,这是我的踩坑经历,提供给大家借鉴,同时也有我的一些解决办法,如果大家有更好的方案,可以一起学习。