H5移动端适配 Flexible方案


Posted in Javascript onOctober 24, 2016

一、移动端一些概念

视觉稿 (选取一款手机的屏幕宽高作为基准)

在前端开发之前,视觉 MM会给我们一个psd文件,称之为视觉稿。

对于移动端开发而言,为了做到页面高清的效果,视觉稿的规范往往会遵循以下两点:

1)首先,选取一款手机的屏幕宽高作为基准(以前是iPhone4 的320×480,现在更多的是iphone6的 375×667)。

2)对于retina 屏幕(如: dpr=2),为了达到高清效果,视觉稿的画布大小会是基准的2 倍,也就是说像素点个数是原来的 4倍(对 iphone6而言:原先的 375×667,就会变成 750×1334)。

问题:

对于 dpr=2的手机,为什么画布大小×2,就可以解决高清问题?

对于 2倍大小的视觉稿,在具体的 css编码中如何还原每一个区块的真实宽高(也就是布局问题)?

标注稿

H5移动端适配 Flexible方案

移动端尺寸

物理像素(physical pixel)

一个物理像素是显示器(手机屏幕)上最小的物理显示单元,在操作系统的调度下,每一个设备像素都有自己的颜色值和亮度值。

设备独立像素(density-independent pixel)

设备独立像素(也叫密度无关像素),可以认为是计算机坐标系统中得一个点,这个点代表一个可以由程序使用的虚拟像素(比如: css像素),然后由相关系统转换为物理像素。

设备像素比(device pixel ratio)

设备像素比(简称 dpr)定义了物理像素和设备独立像素的对应关系,它的值可以按如下的公式的得到: 设备像素比 =物理像素 /设备独立像素 //在某一方向上,x方向或者 y方向。

在Javascript 中,可以通过window.devicePixelRatio获取到当前设备的dpr。

在css 中,可以通过-webkit-device-pixel-ratio,-webkit-min-device-pixel-ratio和 -webkit-max-device-pixel-ratio进行媒体查询,对不同 dpr的设备,做一些样式适配(这里只针对 webkit内核的浏览器和 webview)。

在普通屏幕下,1个 css像素 对应 1个物理像素(1:1)。 在 retina屏幕下,1个 css像素对应 4个物理像素(1:4)。

例:width: 2px;height: 2px; 如下

H5移动端适配 Flexible方案

位图像素

一个位图像素是栅格图像(如:png, jpg, gif等)最小的数据单元。每一个位图像素都包含着一些自身的显示信息(如:显示位置,颜色值,透明度等)。

retina 下图片的展示情况?

理论上,1个位图像素对应于 1个物理像素,图片才能得到完美清晰的展示。

在普通屏幕下是没有问题的,但是在 retina屏幕下就会出现位图像素点不够,从而导致图片模糊的情况。

H5移动端适配 Flexible方案

如上图:对于 dpr=2的 retina屏幕而言,1个位图像素对应于 4个物理像素,

由于单个位图像素不可以再进一步分割,所以只能就近取色,从而导致图片模糊(注意上述的几个颜色值)。

所以,对于图片高清问题,比较好的方案就是两倍图片(@2x)。如:200×300(css pixel)img标签,就需要提供 400×600的图片。

如此一来,位图像素点个数就是原来的 4倍,在 retina屏幕下,位图像素点个数就可以跟物理像素点个数形成 1 : 1的比例,图片自然就清晰了(这也解释了之前留下的一个问题,为啥视觉稿的画布大小要×2?)。

这里就还有另一个问题,如果普通屏幕下,也用了两倍图片,会怎样呢?

很明显,在普通屏幕下,200×300(css pixel)img标签,所对应的物理像素个数就是 200×300个,而两倍图片的位图像素个数则是 200×300*4,所以就出现一个物理像素点对应 4个位图像素点,

所以它的取色也只能通过一定的算法(显示结果就是一张只有原图像素总数四分之一,我们称这个过程叫做 downsampling),肉眼看上去虽然图片不会模糊,但是会觉得图片缺少一些锐利度,或者是有点色差(但还是可以接受的)。

H5移动端适配 Flexible方案

Retina 下,图片高清问题

所以最好的解决办法是:不同的dpr下,加载不同的尺寸的图片。

不管是通过 css媒体查询,还是通过 javascript条件判断都是可以的。那么问题来了,这样的话,不就是要准备两套图片了嘛?(@1x和@2x)

我想,做的好的公司,都会有这么一个图片服务器,通过 url获取参数,然后可以控制图片质量,也可以将图片裁剪成不同的尺寸。

所以我们只需上传大图(@2x),其余小图都交给图片服务器处理,我们只要负责拼接 url即可。

Retina 下,border: 1px 问题

设计师想要的 retina下 border: 1px;,其实就是 1物理像素宽,对于 css而言,可以认为是 border:0.5px;,这是retina 下(dpr=2)下能显示的最小单位。

然而,无奈并不是所有手机浏览器都能识别 border: 0.5px;,ios7以下,android等其他系统里, 0.5px 会被当成为0px 处理,那么如何实现这0.5px 呢?

方案一: 最简单的一个做法就是这样(元素scale):

.scale{ position: relative;}

.scale:after {content:""; position: absolute; bottom:0px; left:0px; right:0px; border-bottom:1px solid #ddd; -webkit-transform:scaleY(.5); -webkit-transform-origin:0 0;}

方案一问题:

通过 transform: scaleY(.5)缩小 0.5倍来达到 0.5px的效果,但是这样 hack实在是不够通用(如:圆角等)。

方案二:页面scale的方案,是比较通用的,几乎满足所有场景。

对于 iphone5(dpr=2),添加如下的 meta标签,设置 viewport(scale 0.5):

页面 scale,必然会带来一些问题:

1)字体大小会被缩放

2)页面布局会被缩放(如: div 的宽高等)

二、多屏适配布局问题

Flexible方案

1) 下载bower下载lib-flexible

将flexible_css.js,flexible.js文件加载到项目中:

<script src="lib/flexible.js"></script>  
<script src="lib/flexible_css.js"></script>

或直接加载阿里CDN的文件:

<script src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/??flexible_css.js,flexible.js"></script>

2).flexible 实际上作用
就是能过JS来动态改写 meta 标签,代码类似这样:

var metaEl = doc.createElement('meta');


var scale = isRetina ? 0.5:1;


metaEl.setAttribute('name', 'viewport');


metaEl.setAttribute('content', 'initial-scale=' + scale + ', 


maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');


if (docEl.firstElementChild) {
 
document.documentElement.firstElementChild.appendChild(metaEl);


} else {
 
var wrap = doc.createElement('div');
 
wrap.appendChild(metaEl);
 
documen.write(wrap.innerHTML);


}

事实上他做了这几样事情:
添加<meta>标签,并动态改写 <meta> 标签
给 <html> 元素添加 data-dpr 属性,并且动态改写 data-dpr 的值
给 <html> 元素添加 font-size 属性,并且动态改写 font-size 的值

3. 布局(以scss为例)

1)基本布局:rem

将视觉稿中的px单位转换成rem单位 :

html元素尺寸 =  视觉稿px值 / rem基准值

例如:视觉稿宽度750px,则html中的缩放倍率就是750 / 10 = 75,然后以这个为基准值,如果视觉稿中某块小内容宽度是150px,则html中这块内容宽度就是 150 / 75 = 2rem

2)字号:px

字号用px单位,并根据情况用[data-dpr]属性来区分不同dpr下的文本字号大小。
为了能更好的利于开发,在实际开发中,我们可以定制一个 font-dpr()Sass混合宏:

@mixin font-dpr($font-size){
 

font-size: $font-size;
 

[data-dpr="2"] & {
 

 font-size: $font-size * 2;


 }


 [data-dpr="3"] & {
 

 font-size: $font-size * 3;


 }


}

设置混合宏之后,在开发中可以直接这样使用:@include font-dpr(24px);

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
LazyLoad 延迟加载(按需加载)
May 31 Javascript
我的Node.js学习之路(一)
Jul 06 Javascript
jquery实现html页面 div 假分页有原理有代码
Sep 06 Javascript
Node.js中的流(Stream)介绍
Mar 30 Javascript
js查看一个函数的执行时间实例代码
Sep 12 Javascript
关于事件mouseover ,mouseout ,mouseenter,mouseleave的区别
Oct 12 Javascript
原生js模拟淘宝购物车项目实战
Nov 18 Javascript
jQuery插件实现带圆点的焦点图片轮播切换
Jan 18 Javascript
JS实现简单易用的手机端浮动窗口显示效果
Sep 07 Javascript
利用Query+bootstrap和js两种方式实现日期选择器
Jan 10 Javascript
解决layui的table插件无法多层级获取json数据的问题
Sep 19 Javascript
解决vue.js中settimeout遇到的问题(时间参数短效果不稳定)
Jul 21 Javascript
javascript的document中的动态添加标签实现方法
Oct 24 #Javascript
Ajax+FormData+javascript实现无刷新表单信息提交
Oct 24 #Javascript
利用JS实现点击按钮后图片自动切换的简单方法
Oct 24 #Javascript
express文件上传中间件Multer详解
Oct 24 #Javascript
用js实现博客打赏功能
Oct 24 #Javascript
jQuery autoComplete插件两种使用方式及动态改变参数值的方法详解
Oct 24 #Javascript
jQuery插件实现可输入和自动匹配的下拉框
Oct 24 #Javascript
You might like
实用函数4
2007/11/08 PHP
yii框架数据库关联查询操作示例
2019/10/14 PHP
PHP数组array类常见操作示例
2020/05/15 PHP
javascript 数据类型转换(parseInt,parseFloat)
2010/07/20 Javascript
javascript函数中的arguments参数
2010/08/01 Javascript
JS方法调用括号的问题探讨
2014/01/24 Javascript
Javascript中Array.prototype.map()详解
2014/10/22 Javascript
jQuery ajax实现省市县三级联动
2021/03/07 Javascript
angularjs 页面自适应高度的方法
2018/01/17 Javascript
axios post提交formdata的实例
2018/03/16 Javascript
微信小程序中时间戳和日期的相互转换问题
2018/07/09 Javascript
React中使用async validator进行表单验证的实例代码
2018/08/17 Javascript
解决vue select当前value没有更新到vue对象属性的问题
2018/08/30 Javascript
axios全局注册,设置token,以及全局设置url请求网段的方法
2018/09/25 Javascript
JS轮播图的实现方法
2020/08/24 Javascript
Python实现Smtplib发送带有各种附件的邮件实例
2017/06/05 Python
Python中的几种矩阵乘法(小结)
2019/07/10 Python
python调用其他文件函数或类的示例
2019/07/16 Python
用pandas划分数据集实现训练集和测试集
2020/07/20 Python
python软件测试Jmeter性能测试JDBC Request(结合数据库)的使用详解
2021/01/26 Python
前端水印的简单实现代码示例
2020/12/02 HTML / CSS
北美领先的牛仔品牌:Buffalo David Bitton
2017/05/22 全球购物
Bath & Body Works阿联酋:在线购买沐浴和身体用品
2021/02/27 全球购物
SQL语言面试题
2013/08/27 面试题
如何写一个Java类既可以用作applet也可以用作java应用
2016/01/18 面试题
大学校庆策划书
2014/01/31 职场文书
财经学院自荐信范文
2014/02/02 职场文书
火灾现场处置方案
2014/05/28 职场文书
国庆促销活动总结
2014/08/29 职场文书
五好家庭事迹材料
2014/12/20 职场文书
农村党员干部承诺书
2015/05/04 职场文书
如何起草一份正确的合伙创业协议书?
2019/07/04 职场文书
vue 实现上传组件
2021/05/31 Vue.js
浅谈Python中的正则表达式
2021/06/28 Python
MySQL修炼之联结与集合浅析
2021/10/05 MySQL
MYSQL 运算符总结
2021/11/11 MySQL