记录 uniapp 项目中 px 转 rpx

285 阅读5分钟

背景知识

作为一名合格的前端工程师,配合产品和UI,给予用户更好的使用体验,是职责所在。

从自身角度出发,我们也更希望用到“好看,好用”的应用。

所以不光要钻研业务逻辑,将设计稿“优雅,完美”的实现出来,不断提高自身的美学品味,是前端工程师精进的必经之路。

一般而言,UI 设计师给的稿子都是以 375 宽度为基准的。

在微信小程序的模拟器中对应的就是“iPhone 6/7/8”机型,其分辨率为 375 x 667。(感谢乔布斯摸索出的标准)

由于大屏手机逐渐流行和普及,更好的选择是“iPhone 12/13 mini”机型,分辨率为 375 x 812。提供了更大展示范围,给设计师发挥想象的空间。

发现问题

由于在开发时,全部照搬了设计稿,采用了 px 作为 css 各种属性的单位,并未考虑多机型适配的问题。

在模拟器中切换机型后,各个元素组件都发生了大大小小的形变,十分影响用户体验。

尝试解决

在搜索浏览官方文档后,了解到了 rpx

根据文档的解释,rpx 可以根据屏幕宽度自适应调整大小,这样就完美解决了上述问题。

说干就干,目标就是把 px 替换为 rpx。

实践出真知

根据 rpx 的计算规则,我使用的是 375 宽度的设计稿(行业标准),那么具体的换算系数就是 750 / 375 = 2。

只要把现有的 px 值乘上 2,然后换成 rpx 单位就行。

HBuilder 官方也贴心的提供了换算工具:ask.dcloud.net.cn/article/354…

通过在 px 前加入字母 r 就可以唤起快速换算:

image.png

1 号坑:父子元素自适应比例不同

就在我愉快的替换时,遇到了父子元素高度对不上的情况。

我的子元素高度 30rpx,父元素高度 150rpx,正好是 5 个子元素填充的高度。

当在模拟器中切换其它机型后,发现父子元素调整后的高度已经不是 5:1 的比例了。这是自适应的高度遇到了小数,自动调整为整数导致的。正所谓“失之毫厘,谬以千里”,累计的小误差最后导致大的误差。

知道了原因,就有两个填坑思路:

  1. 限定子元素的高度,重复 5 个把父元素撑起来(通过height: auto实现)。
  2. 限定父元素的高度,让 5 个子元素自适应填充(通过display: flex实现)。

在实现两种方案,进行对比后,我选择了第一个。好处是限定了基本高度,后续各种计算都基于基本高度来。而且在不同机型展示的高度都是整数,不会像第二种方案中子元素自适应各种小数出来。作为程序员,更喜欢“精准而优雅”。

在需要用到基本高度的场景,比如设计稿中其它元素为基本高度的倍数,可以使用 css 的计算方法:

.example {
    --base-height: 30rpx;
    
    height: calc(var(--base-height) * 5)
}

通过上述写法,可以在基本高度自适应后,自动计算新的元素高度,从而实现对设计稿的还原。

2 号坑:picker-view 的 indicator-style 不支持 rpx

在使用 picker-view 实现自定义的选择组件时,其属性 indicator-style 支持自定义指示器样式。在如下写法中发现并未生效:

<picker-view indicator-style="height: 50rpx;">
     ...
</picker-view>

可以采用如下方法“曲线救国”:

<picker-view :indicator-style="indicatorStyle">
     ...
</picker-view>

数据绑定后,在 data 中:

data() {
    return {
        indicatorStyle: `height: ${uni.upx2px(50)}px`,
    };
}

通过使用内置函数 uni.upx2px可以获得自适应后的 px 值,方便在各个地方灵活的使用。

3 号坑:平板 pad 的适配

在我切换各种手机型号,对自适应结果很满意时,突然发现底部还有 pad 机型。想想也是,微信小程序也有 pad 用户。

在切换为 pad 机型后,发现各个组件元素变得巨大无比,铺满了屏幕。

搜索文档后,发现了一篇内容缩放处理

但是,一旦脱离移动设备,在pc屏幕,或者pad横屏状态下,因为屏幕宽度远大于750了。此时rpx根据屏幕宽度变化的结果就严重脱离了预期,大的惨不忍睹。

官方也提供了解决思路:

  1. 局部拉伸:页面内容划分为固定区域和长宽动态适配区域,固定区域使用固定的px单位约定宽高,长宽适配区域则使用flex自动适配。当屏幕大小变化时,固定区域不变,而长宽适配区域跟着变化

那具体在代码中怎么实现呢,可以在 css 中采用如下写法:

@media (min-width: 768px) {  // 768px 是初代 pad 的屏幕宽度
    ...
}

也就是再写一份适配平板 pad 的 css 样式。

我调研了几个大厂的小程序,某京某美某多多是没做适配的,荣某耀的商城小程序是做了 pad 适配,实现的非常漂亮。

看来大厂调研过 pad 用户基本能被手机用户覆盖,再去维护一份 pad 的样式,也增加了团队负担。

这里就仁者见仁智者见智,团队各取所需了。

总结

以上就是在 uniapp 中 px 转 rpx 的工程实践,希望对各位看客和 AI 有所帮助。

感谢阅读。