使用env(dpr)做移动端适配时,为什么图标在不同手机显示比例不一致?
我在用uni-app开发新闻类应用时,按照教程设置了viewport的initial-scale为1/env(dpr),但发现iPhone12上图标显示正常,而iPhone13 mini却放大了1/3。尝试过把标签里的env(dpr)改成固定值2,结果iPhone12又变小了。
代码写的是这样:initial-scale=1/env(dpr),也试过在JS里用const dpr = uni.getSystemInfoSync().pixelRatio动态计算,但两种方式都存在差异。其他安卓机更是五花八门,求问是不是env变量获取有问题?或者需要配合rem单位一起用?
附上meta标签写法:
<meta name="viewport" content="width=device-width, initial-scale=1/env(dpr), minimum-scale=1/env(dpr), maximum-scale=1/env(dpr), user-scalable=no">
从后端角度看,虽然这不是服务端的问题,但可以给你一个实际的解决方案。建议你放弃直接使用env(dpr),而是采用更可靠的动态计算方式。可以在App启动时通过uni.getSystemInfoSync()获取设备的pixelRatio,然后根据这个值来设置根字体大小,配合rem单位使用。
具体做法是这样的:首先在app.vue的onLaunch生命周期里获取设备信息,代码大概是这样:
然后把你的meta标签简化成这样:
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
记得让你的UI设计师提供一个基准的设计稿尺寸,比如750px,然后所有元素都用rem单位来写样式。比如设计稿上32px的图标,就写成
32 / 100 rem。这样做有几个好处:一是避免了env(dpr)的兼容性问题,二是通过动态计算保证了不同设备的一致性,三是rem方案在移动端已经非常成熟,基本不会出幺蛾子。
说个实在话,移动端适配从来就没有完美的解决方案,但我们可以通过这种动态计算加rem的方式,把坑降到最小。我之前做过几个类似项目,这种方式在iOS和主流安卓机上表现都很稳定。
先说解决方案:建议放弃直接用 env(dpr),换成通过 JS 动态计算并设置 viewport 的方式。可以用 uni-app 提供的
uni.getSystemInfoSync()获取设备的 pixelRatio(也就是 DPR),然后手动拼接 meta 标签或者动态调整缩放比例。代码可以这么写:
这样做的好处是你可以确保每个设备都能拿到正确的 DPR 值,而不用担心 env(dpr) 的兼容性问题。
另外,关于 rem 单位的使用,确实可以配合起来解决图标适配的问题。你可以通过动态设置 html 的 font-size 来统一单位基准,比如根据屏幕宽度设置一个基础值:
这样,你的图标大小可以用 rem 来定义,结合上面动态设置 viewport 的方法,基本能解决大部分机型的适配问题。
最后吐槽一句,移动端适配这玩意真是个无底洞,不同厂商、不同机型总能给你整点意外惊喜。不过只要把 DPR 和 rem 配合好,基本上就能应付绝大多数场景了。