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 相关文章推荐
jquery.ui.draggable中文文档
Nov 24 Javascript
JQuery的Alert消息框插件使用介绍
Oct 09 Javascript
jQuery 表单验证扩展(三)
Oct 20 Javascript
js下通过prototype扩展实现indexOf的代码
Dec 08 Javascript
js使用split函数按照多个字符对字符串进行分割的方法
Mar 20 Javascript
如何使用jquery easyui创建标签组件
Nov 18 Javascript
JavaScript中值类型和引用类型的区别
Feb 23 Javascript
详解Vue.js 2.0 如何使用axios
Apr 21 Javascript
使用vue中的v-for遍历二维数组的方法
Mar 07 Javascript
js中获取URL参数的共用方法getRequest()方法实例详解
Oct 24 Javascript
使用JQuery自动完成插件Auto Complete详解
Jun 18 jQuery
JavaScript实现身份证验证代码实例
Aug 26 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
PHP中for循环语句的几种变型
2006/11/26 PHP
IP攻击升级,程序改进以对付新的攻击
2010/11/23 PHP
PHP设计模式之装饰器模式定义与用法详解
2018/04/02 PHP
通过下拉框的值来确定输入框是否可以为空的代码
2011/10/18 Javascript
网页加载时页面显示进度条加载完成之后显示网页内容
2012/12/23 Javascript
jquery实现控制表格行高亮实例
2013/06/05 Javascript
JavaScript 命名空间 使用介绍
2013/08/29 Javascript
JS操作Cookie写入和读取实例代码
2013/10/20 Javascript
jQuery插件jQuery-JSONP开发ajax调用使用注意事项
2013/11/22 Javascript
jQuery实现的超简单点赞效果实例分析
2015/12/31 Javascript
深入解析桶排序算法及Node.js上JavaScript的代码实现
2016/07/06 Javascript
js实现对table的增加行和删除行的操作方法
2016/10/13 Javascript
Angular中$state.go页面跳转并传递参数的方法
2017/05/09 Javascript
给vue项目添加ESLint的详细步骤
2017/09/29 Javascript
AngularJS模态框模板ngDialog的使用详解
2018/05/11 Javascript
在移动端使用vue-router和keep-alive的方法示例
2018/12/02 Javascript
小程序实现左滑删除效果
2019/07/25 Javascript
javascript实现的图片预览和上传功能示例【兼容IE 9】
2020/05/01 Javascript
python enumerate函数的使用方法总结
2017/11/15 Python
python基于twisted框架编写简单聊天室
2018/01/02 Python
python方法生成txt标签文件的实例代码
2018/05/10 Python
pandas.loc 选取指定列进行操作的实例
2018/05/18 Python
pyQT5 实现窗体之间传值的示例
2019/06/20 Python
python开启debug模式的方法
2019/06/27 Python
Python单例模式的四种创建方式实例解析
2020/03/04 Python
pytorch中的weight-initilzation用法
2020/06/24 Python
解决阿里云邮件发送不能使用25端口问题
2020/08/07 Python
Python自动巡检H3C交换机实现过程解析
2020/08/14 Python
Python GUI之tkinter窗口视窗教程大集合(推荐)
2020/10/20 Python
pycharm 复制代码出现空格的解决方式
2021/01/15 Python
Canvas与Image互相转换示例代码
2013/08/09 HTML / CSS
运动会广播稿30字
2014/01/21 职场文书
《跨越百年的美丽》教学反思
2014/02/11 职场文书
《雪地里的小画家》教学反思
2014/02/22 职场文书
答辩状格式范本
2015/05/22 职场文书
西安事变观后感
2015/06/12 职场文书