如何实现微信小程序的横屏及适配
微信小程序如何横屏
从小程序基础库版本 2.4.0 开始,小程序在手机上支持屏幕旋转。使小程序中的页面支持屏幕旋转的方法是:在 app.json
的 window
段中设置 "pageOrientation": "auto"
,或在页面 json 文件中配置 "pageOrientation": "auto"
。
PS:1、以这种方式实现小程序屏幕旋转,需要用户关闭手机上的“屏幕锁定”选项
PS:2、由于开启横屏需要修改json文件的配置,而这个文件我们无法在程序运行中进行修改,故我们无法通过点击按钮或其他操作去使手机屏幕发生旋转,只是是设置为"pageOrientation": "auto"
用户主动旋转手机触发
PS:3、我们可以在进入某一个页面的时候,固定屏幕横屏展示,设置"pageOrientation": "landscape "
如何获取当前屏幕状态
使用 selectorQuery.selectViewport可以获取到当前的屏幕状态。这种方式比较麻烦,这里介绍一种使用wx.onWindowResize
进行监听的方式。
onShow() {
let that = this;
wx.onWindowResize(function(res) {
if (res.deviceOrientation === 'landscape') {
that.isRotating = true;
} else {
that.isRotating = false;
}
})
}
上面代码中,我们可以在wx.onWindowResize
函数的回调中获取到当前屏幕的方向,并赋值给isRotating
。当然,我们还可以在回调中拿到windowWidth
(变化后的窗口宽度,单位 px)和windowHeight
(变化后的窗口高度,单位 px)属性。
wx.onWindowResize
函数是一个监听函数,类似Vue
中的watch
,我们可以把它放到onShow
中。
横屏后出现的适配问题
我们都知道,微信小程序在竖屏状态下,宽度100%,100VW的值为750rpx。但是在横屏之后,750rpx的实际宽度为手机屏幕的高。如图:
竖屏状态使用rpx,px进行布局 横屏状态使用rpx,px进行布局1 横屏状态使用rpx,px进行布局2在这种情况下,我们的界面将会变大。
举个简单例子,假如手机屏幕的宽高比为1:2,我们有一个按钮大小为100rpx100rpx,那么在竖屏状态下,显示正常,横屏状态下,按钮的显示宽高将会变成原来的2倍,当然他仍然是100rpx100rpx,但是显示出来却是变大了。
横屏后的适配方案
使用px进行布局
我们可以看到,使用px
进行布局时,横屏之后元素并没有变大,所以这种方案是可行的。
但是,我们可以看到的是,375px在横屏时并没有占满全屏,也就是px
和rpx
之间并不是简单的1:2的对应关系。
这里我们不讨论个物理像素、pt、px之间复杂的关系(/ω\)
所以,使用
px
布局,也不是那么好用。
使用vmin进行布局
先介绍下css3的两个属性vmax
和vmin
vmax 相对于视口的宽度或高度中较大的那个。其中最大的那个被均分为100单位的vmax
vmin 相对于视口的宽度或高度中较小的那个。其中最小的那个被均分为100单位的vmin
文档说明
在这里我们只用到了vmin
。
当我们在竖屏时候,100vmin
的取值为手机屏幕宽度,当横屏时候,100vmin
的取值仍然为手机屏幕宽度,所以以vmin
为单位的元素,在手机屏幕发生旋转的时候,其显示大小并不会发生改变(毕竟不管横屏竖屏,100vmin
都等于屏幕的宽度)。
在使用rpx
进行布局时,750rpx
的取值为手机屏幕的宽度,而在使用vmin
时,100vmin
的取值为手机屏幕的宽度,所以,rpx
和vmin
之间存在一个换算关系,即:x rpx=( x * 100 / 750)vmin
。举个例子,75rpx
转化为vmin
为75 * 100 / 750 = 10 vmin
。所以,我们只要将rpx
转化成vmin
就可以愉快的码页面了~
使用scss进行转化
在实际开发中,我们不可能去手动计算每一个vmin
的值,由于我用的是scss
,所以我用scss
进行了一下预处理。这里提供两种方式,一种是css
函数,另一种是css mixin
//css函数
@function tovmin($rpx){//$rpx为需要转换的字号
@return #{$rpx * 100 / 750}vmin;
}
//使用方式
.slideAddPanel {
width: tovmin(48);
height: tovmin(80);
background: rgba(0, 0, 0, 0.5);
box-shadow: 0 tovmin(2) tovmin(12) 0 rgba(0, 0, 0, 0.2);
line-height: tovmin(80);
border-radius: 0 tovmin(10) tovmin(10) 0;
}
//css mixin
@mixin upx2vmin($property, $values...) {
$max: length($values);//返回$values列表的长度值
$pxValues: '';
$remValues: '';
@for $i from 1 through $max {
$value: nth($values, $i);
$remValues: #{$remValues + ($value * 100 / 750)}vmin;
@if $i < $max {
$remValues: #{$remValues + " "};
}
}
#{$property}: $remValues;
}
//使用方式
.slideAddPanel {
@include remCalc(width,45);
@include remCalc(margin,1,.5,2,3);
}
PS:这两种方法均来自网络,我还是比较喜欢第一种~