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 相关文章推荐
JavaScript入门教程(8) Location地址对象
Jan 31 Javascript
Jquery Ajax学习实例6 向WebService发出请求,返回DataSet(XML) 异步调用
Mar 18 Javascript
javascript中Function类型详解
Apr 28 Javascript
jQuery消息提示框插件Tipso
May 04 Javascript
JavaScript实现倒计时代码段Item1(非常实用)
Nov 03 Javascript
浅析jQuery事件之on()方法绑定多个选择器,多个事件
Apr 27 Javascript
javaScript中定义类或对象的五种方式总结
Dec 04 Javascript
基于React实现表单数据的添加和删除详解
Mar 14 Javascript
浅谈webpack+react多页面开发终极架构
Nov 11 Javascript
angular多语言配置详解
May 16 Javascript
JavaScript计算正方形面积
Nov 26 Javascript
使用Ajax实现进度条的绘制
Apr 07 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伪静态的实现详细介绍
2013/04/28 PHP
php微信支付之APP支付方法
2015/03/04 PHP
PHP生成唯一订单号
2015/07/05 PHP
Yii实现简单分页的方法
2016/04/29 PHP
Yii基于CActiveForm的Ajax数据验证用法示例
2016/07/14 PHP
javascript获得服务器端控件的ID的实现代码
2011/12/28 Javascript
利用jquery动画特效和css打造的侧边弹出垂直导航
2014/04/04 Javascript
jQuery移动web开发之页面跳转和加载外部页面的实现
2015/12/04 Javascript
原生态js,鼠标按下后,经过了那些单元格的简单实例
2016/08/11 Javascript
Bootstrap select多选下拉框实现代码
2016/12/23 Javascript
JavaScript正则表达式exec/g实现多次循环用法示例
2017/01/17 Javascript
bootstrap Validator 模态框、jsp、表单验证 Ajax提交功能
2017/02/17 Javascript
详解Angular 4 表单快速入门
2017/06/05 Javascript
详解JS浏览器事件循环机制
2019/03/27 Javascript
深入了解响应式React Native Echarts组件
2019/05/29 Javascript
如何编写一个 Webpack Loader的实现
2020/10/18 Javascript
JS实现购物车基本功能
2020/11/08 Javascript
[02:25]专访DOTA2负责人Erik 国际邀请赛暂不会离开西雅
2014/07/21 DOTA
[02:07]DOTA2新英雄展现中国元素,完美“圣典”亮相央视
2016/12/19 DOTA
Python自动化测试工具Splinter简介和使用实例
2014/05/13 Python
python基础教程之对象和类的实际运用
2014/08/29 Python
使用rst2pdf实现将sphinx生成PDF
2016/06/07 Python
Python排序搜索基本算法之堆排序实例详解
2017/12/08 Python
python列表的增删改查实例代码
2018/01/30 Python
对python中Librosa的mfcc步骤详解
2019/01/09 Python
Python 实现两个服务器之间文件的上传方法
2019/02/13 Python
python实现Excel文件转换为TXT文件
2019/04/28 Python
numpy linalg模块的具体使用方法
2019/05/26 Python
Python实现TCP通信的示例代码
2019/09/09 Python
Python 迭代,for...in遍历,迭代原理与应用示例
2019/10/12 Python
学会迭代器设计模式,帮你大幅提升python性能
2021/01/03 Python
教师自我评价范例
2013/09/24 职场文书
学生请假条格式
2014/04/11 职场文书
募捐倡议书
2014/04/14 职场文书
4S店客服专员岗位职责
2015/04/07 职场文书
Redis 哨兵机制及配置实现
2022/03/25 Redis