浅析小程序响应式像素实现原理

简介: 谈谈微信小程序的响应式像素是如何实现的

本次分享我们来谈谈微信小程序的响应式像素是如何实现的。

官方文档说明

WXSS (WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式。

WXSS 用来决定 WXML 的组件应该怎么显示。

为了适应广大的前端开发者,WXSS 具有 CSS 大部分特性。同时为了更适合开发微信小程序,WXSS 对 CSS 进行了扩充以及修改。

尺寸单位

  • rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。

那么在 iPhone6 的环境下,为什么写了2rpx就会等同于1px呢?

带着疑问我们可以在解包之后的文件中找到答案。

首先如果你读过博主前面的文章,应该会知道小程序的本质是一个混合应用,是一堆js代码,页面结构及业务逻辑都是打包为js的,然后wxss样式本身也是用服务端的编译器去打包为js的,所以我们就可以从源码上略知一二了。

如果你试着去寻找一下,会发现类似如下的代码。

  • 这里我们节选一部分代码来帮助理解所谓响应式像素的实现过程。

var BASE_DEVICE_WIDTH = 750;
var isIOS = navigator.userAgent.match('iPhone');
var deviceWidth = window.screen.width || 375;
var deviceDPR = window.devicePixelRatio || 2;
var checkDeviceWidth =
window.__checkDeviceWidth__ ||
function () {
  var newDeviceWidth = window.screen.width || 375;
  var newDeviceDPR = window.devicePixelRatio || 2;
  var newDeviceHeight = window.screen.height || 375;
  if (
    window.screen.orientation &&
    /^landscape/.test(window.screen.orientation.type || '')
  )
    newDeviceWidth = newDeviceHeight;
  if (newDeviceWidth !== deviceWidth || newDeviceDPR !== deviceDPR) {
    deviceWidth = newDeviceWidth;
    deviceDPR = newDeviceDPR;
  }
};
checkDeviceWidth();
var eps = 1e-4;
var transformRPX =
window.__transformRpx__ ||
function (number, newDeviceWidth) {
  if (number === 0) return 0;
  number =
    (number / BASE_DEVICE_WIDTH) * (newDeviceWidth || deviceWidth);
  number = Math.floor(number + eps);
  if (number === 0) {
    if (deviceDPR === 1 || !isIOS) {
      return 1;
    } else {
      return 0.5;
    }
  }
  return number;
};

下面我们来一起看下吧~
小程序页面在注册的过程中会定义一些变量:

  • BASE_DEVICE_WIDTH,值为750,也就是官网所说的基准设备宽度(规定屏幕宽为750rpx)。
  • deviceWidth,取值为屏幕宽度,默认值375。
  • deviceDPR,设备上物理像素和逻辑像素的比例,所说的像素密度,默认为2。

另外通过用户代理(UA)来判断设备是否为IOS,之后定义了一个全局变量checkDeviceWidth指向的一个挂载在window对象下全局函数__checkDeviceWidth__,如果window下面没这个对象则直接返回一段检查屏幕宽高的函数。如果是横屏情况则会把屏幕宽度设为高度值,重新设置宽高。
之后直接执行了这段函数checkDeviceWidth

再往下就是本次的关键部分了,定义了一个名为transformRPX的函数,看意思就知道了,作用是转化rpx单位的,该函数支持传入两个参数:

  • number
  • newDeviceWidth

这里大家应该明白了,传入的第一个参数就是我们手写的wxss样式某标签的具体宽高值,第二个则是设备宽度。
函数内容也大致说下吧:

  • 如果传的是0,比如0rpx,那转换之后自然就是0了
  • 如果不是 0,则按公式((number / BASE_DEVICE_WIDTH) * (newDeviceWidth || deviceWidth))做了换算,就是按照传入值与基准设备宽度得到的比率乘以当前设备宽度
  • 并且这里利用1e-4的eps值做了小量比较,即传入的number值转换之后加上eps并向下取整了。
  • 并且取整之后为0的情况,如果像素密度为1或者是非IOS设备则返回1,像素密度如果大的,或者IOS的设备就返回了0.5。

大致的作用就解析到这里吧,页面样式最终转换后还是以px为单位进行渲染的。

所以会有同学又有疑问了,小程序运行环境中的webview下面到底认不识rpx呢?

这里其实大家应该大概了解微信小程序的是如何根据屏幕宽度进行自适应显示的思路了。

当然这里只是简要介绍了一下,真实情况要比这个复杂,我们从视图层基础库的代码中也可以窥探到一些有意思的东西,比如组件占位符的样式,内联样式的转换等等(有兴趣的同学可以试着在基础库的 WAWebview.js 文件中去搜索一下 transformRpx)。

参考资料

相关文章
|
3月前
|
缓存 开发框架 JavaScript
人人都能看懂的鸿蒙 “JS 小程序” 数据绑定原理 | 解读鸿蒙源码
人人都能看懂的鸿蒙 “JS 小程序” 数据绑定原理 | 解读鸿蒙源码
|
6月前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的《数据库系统原理》课程平台附带文章和源代码设计说明文档ppt
基于ssm+vue.js+uniapp小程序的《数据库系统原理》课程平台附带文章和源代码设计说明文档ppt
43 1
|
6月前
|
小程序 JavaScript 前端开发
简述微信小程序原理
简述微信小程序原理
|
小程序
微信小程序-新增RPX响应式单位
!> 在企业开发中,拿到设计师设计的750设计图之后,我们只需要将模拟器调整为 iphone6,然后将设计图上标注的 px 乘以2,写到样式中,单位使用 rpx 即可。
89 0
|
6月前
|
缓存 小程序 JavaScript
支付宝小程序性能优化原理及手段
支付宝小程序性能优化原理及手段
242 11
|
XML 移动开发 小程序
微信小程序原理
微信小程序原理
|
前端开发 小程序 数据安全/隐私保护
|
缓存 移动开发 JSON
微信小程序底层框架实现原理|万字长文(三)
微信小程序底层框架实现原理|万字长文
567 0
|
JavaScript 小程序 前端开发
微信小程序底层框架实现原理|万字长文(二)
微信小程序底层框架实现原理|万字长文
232 0
|
缓存 JSON 小程序
微信小程序底层框架实现原理|万字长文(一)
微信小程序底层框架实现原理|万字长文
459 0