1.项目描述
一款App+h5进行混合开发,App通过webview方式对h5进行远程加载。h5采用了vuejs进行开发,适配采用了px2rem插件方式进行批量转换。
2.项目异常现象
混合开发增加了调试的难度,也增加了人员开发的沟通成本。使用了rem单位进行适配在大多数机型表现还算OK。我们通常的做法是设置html 根字体大小,然后通过rem来转换。如果设置根字体是100px=1rem,div宽如果是200px,则值为2rem。但是在现今碎片化严重的安卓机环境中,。这种想当然的想法会被打脸。经过查询了一些资料
后得到一些情况,在大多数情况下rem的兼容性还是很好。但是也会出现一些安卓机在计算过程中出比例计算不正常的情况。所以这种兼容性需要进行排查。
3.排查手段
WebAPI 提供了一个叫Window.getComputedStyle() 方法,这个方法能够计算出css属性值。
摘要
Window.getComputedStyle()方法返回一个对象,该对象在应用活动样式表并解析这些值可能包含的任何基本计算后报告元素的所有CSS属性的值。 私有的CSS属性值可以通过对象提供的API或通过简单地使用CSS属性名称进行索引来访问。
有了这个计算方法,可以对一些元素进行信息获取。
const getBodyWidth = function (element){
if (window.getComputedStyle) {
return parseInt(window.getComputedStyle(element, null)['width']);
} else {
return parseInt(element.currentStyle['width']);
}
}
var body = document.getElementsByTagName('body')[0];
body.style.width = '10rem';
const bodyWidth = getBodyWidth(body);
console.log(bodyWidth);//获取得到一个宽度
4.小试实验
首先编辑一个按钮,然后引入rem适配。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>rem实验</title>
</head>
<style>
body,html,div{
margin: 0;
padding: 0;
}
.ui-btn-pay {
display: inline-block;
width: 4.5rem;
height: 0.88rem;
text-align: center;
line-height: 0.88rem;
background: linear-gradient(90deg,#c422c2,#8725f7);
border-radius:0.48rem;
color: #fff;
font-size: 0.28rem;
margin: 0 auto;
}
.ui-btn-pay:active{
opacity: 0.8;
}
</style>
<body>
<div style="text-align: center;">
<div class="ui-btn-pay">
马上对象
</div>
</div>
<script src="./test.js"></script>
</body>
</html>
5.引入js进行适配
我们以字体100px进行计算,设计稿尺寸750(可以是375),然后进行比例计算。这个比例计算以文档的宽和设计稿宽进行比较,得到缩放比例。
拿到了这个比例好,再和根字体大小进行缩放。
在大多数情况下,这种计算还算可以的。只是在一些安卓机器出现了问题。我举个例子。
当你设置body为rem单位的时候,你可能会认为获取到body的宽度和输入 的值是一样。当初我也是这样认为这是理所当然的事情。不然这个就是有计算的问题。
100px = 1rem。那么200px = 2rem 是理所当然。实际上打个比方将body =2rem,获取回来的不一定是等于200px
当然这种机型是极小数出现,大部分情况还是会相同。所以可以尝试试探设置后,和原来输入的值到底相不相等。有了这个基础后,这个试探性设计就可以结合到原来普遍的rem计算缩放。
var body = document.getElementsByTagName('body')[0];
body.style.width = (width/rem)+'rem';//赋值进行试探
function rem(){
const baseSize = 100;
const width = document.documentElement.clientWidth;
var scale = width / 750;
var rem = baseSize * scale;
document.documentElement.style.fontSize = rem + 'px';
testFontSize(width,rem);
}
//检测字体设置是否真的生效
function testFontSize(width,rem){
var body = document.getElementsByTagName('body')[0];
body.style.width = (width/rem)+'rem';//赋值进行试探
const getBodyWidth = function (element){
if (window.getComputedStyle) {
return parseInt(window.getComputedStyle(element, null)['width']);
} else {
return parseInt(element.currentStyle['width']);
}
}
const bodyWidth = getBodyWidth(body);
//测试对比值情况
console.log("width:"+width+" "+"bodyWidth:"+bodyWidth);
alert("width:"+width+" "+"bodyWidth:"+bodyWidth);
if (bodyWidth != width) {
const scale = width/bodyWidth;//计算比例算出合理比例
rem = rem * scale;
document.documentElement.style.fontSize = rem + 'px';
}
body.style.width = '100%';
}
rem();
window.addEventListener('resize', function () {
rem();
}, false);
6.综述
在大多数的rem还是准确的,这种不准确的机型猜测是一些系统版本引起。属于版本问题。事实上,这种问题不应该发生,安卓机器碎片化严重的时候,前端复杂度已经大大增加了不少的试错成本。造成了很大困扰。