相关知识

viewport直译为视口,也就是屏幕上网页的可视区域;

meta标签内可指定viewport的宽度;

示例代码:

1
2
<meta name="viewport" content="width=640">
// width 一个正整数或'device-width'(设备宽度)

在CSS3中对应的技术实现——新单位vwvhvmaxvmin

 vw 相对于视口的宽度,视口被均分为100单位的vw。
 vh 相对于视口的高度,视口被均分为100单位的vh。
 vmax 相对于视口的宽度或高度中较大的那个,其中最大的那个被均分为100单位的vmax。
 vmin 相对于视口的宽度或高度中较小的那个,其中最小的那个被均分为100单位的vmin。

起因

重申一遍概念,viewport直译为视口,也就是屏幕上网页的可视区域,网页的可视区域!!!

问题来了,当我们的页面中存在可获得焦点的区域(如输入框)时,手机的虚拟键盘会被唤起,此时,我们的页面如果应用的是vh的单位,网页的可视区域就会变为页面顶端到虚拟键盘顶端的高度,也就是说,viewport的高度变小了,这TM就尴尬了,页面布局会跟着缩小,缩小啊~~~

解决思路

既然是因为视口的变动而引起布局的变化,那么我们何不让其在视口变动之前将布局定下来。

思路:

在视口右下角新增一个宽高皆为零的元素。
获得新增元素距离左边和顶边边界的距离,从而得出vwvh
移除该元素。

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var viewport = (function(){
var point = document.createElement("div");
point.style.cssText = "position:fixed;width:0;height:0;right:0;bottom:0;";
document.body.appendChild(point);
var vh = point.offsetTop + point.parentNode.offsetTop;
var vw = point.offsetLeft + point.parentNode.offsetLeft;
document.body.removeChild(point);
return {
vh: vh,
vw: vw,
vmax: (vh > vw ? vh : vw),
vmin: (vh > vw ? vw : vh)
};
})();

数据获取方式:

viewport.vw 视口宽度(整数数值)
viewport.vh 视口高度(整数数值)
viewport.vmax 相对于视口的宽度或高度中较大的那个(整数数值)
viewport.vmin 相对于视口的宽度或高度中较小的那个(整数数值)

实际应用

1.通过上述方式我们可以得到准确的视口信息。

2.解决键盘唤起时由视口变换引起的布局变形。

思路:

将css中使用了vwvhvmaxvmin单位的样式找出。
转换为px单位。
替换原有样式。

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function each(context,func){
Array.prototype.forEach.call(context,func);
}
var reg = /[0-9]+(\.?[0-9]+)?v[w|h|max|min]/g;
each(document.styleSheets,function(sheet){
var rules = sheet.cssRules || sheet.rules;
each(rules,function(rule){
var style = rule.style;
style&&each(style,function(name){
reg.test(style[name])&&(style[name]=style[name].replace(reg,function(item){
return parseFloat(item)/100 * viewport[item.match(/v[w|h|max|min]/)[0]] + 'px';
}));
});
});
});

Tips:StyleSheetList是一个类数组对象

何莹亮原创技术文章,转载请注明出处:https://heyingliang.github.io/mark/2018/02/23/getview/

目录