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乱码与contentType属性设置问题解决方案
Jan 07 Javascript
防止文件缓存的js代码
Jan 10 Javascript
javascript正则表达式使用replace()替换手机号的方法
Jan 19 Javascript
跟我学习javascript的垃圾回收机制与内存管理
Nov 23 Javascript
图文详解Heap Sort堆排序算法及JavaScript的代码实现
May 04 Javascript
微信小程序使用Socket的实例
Sep 19 Javascript
JavaScript门面模式详解
Oct 19 Javascript
layui-laydate时间日历控件使用方法详解
Nov 15 Javascript
详解element-ui表格中勾选checkbox,高亮当前行
Sep 02 Javascript
微信小程序自定义波浪组件使用方法详解
Sep 21 Javascript
JS 设计模式之:工厂模式定义与实现方法浅析
May 06 Javascript
全面解析js中的原型,原型对象,原型链
Jan 25 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 正则表达式小结
2009/08/31 PHP
php面向对象全攻略 (四)构造方法与析构方法
2009/09/30 PHP
PHPWind 发帖回帖Api PHP版打包下载
2010/02/08 PHP
PHP读取xml方法介绍
2013/01/12 PHP
php命令行(cli)模式下报require 加载路径错误的解决方法
2015/11/23 PHP
jquery不支持toggle()高(新)版本的问题解决
2016/09/24 PHP
php中strtotime函数性能分析
2016/11/20 PHP
YII分模块加载路由的实现方法
2018/10/01 PHP
js不完美解决click和dblclick事件冲突问题
2012/07/16 Javascript
Jquery创建一个层当鼠标移动到层上面不消失效果
2013/12/12 Javascript
Jqgrid表格随窗口大小改变而改变的简单实例
2013/12/28 Javascript
jQuery中parents()和parent()的区别分析
2014/10/28 Javascript
javascript设计模式--策略模式之输入验证
2015/11/27 Javascript
基于jQuery实现以手风琴方式展开和折叠导航菜单
2016/01/28 Javascript
jQuery表单验证简单示例
2016/10/17 Javascript
jQuery Ajax请求后台数据并在前台接收
2016/12/10 Javascript
jQuery实现的背景颜色渐变动画效果示例
2017/03/24 jQuery
Nodejs实现多房间简易聊天室功能
2017/06/20 NodeJs
浅谈vuex之mutation和action的基本使用
2017/08/29 Javascript
js canvas实现橡皮擦效果
2018/12/20 Javascript
vue:el-input输入时限制输入的类型操作
2020/08/05 Javascript
原生js实现购物车功能
2020/09/23 Javascript
[33:39]DOTA2上海特级锦标赛C组小组赛#2 LGD VS Newbee第二局
2016/02/27 DOTA
[44:40]2018DOTA2亚洲邀请赛3月30日 小组赛A组Liquid VS OG
2018/03/31 DOTA
Python异常学习笔记
2015/02/03 Python
python爬虫之urllib库常用方法用法总结大全
2018/11/14 Python
Python 微信之获取好友昵称并制作wordcloud的实例
2019/02/21 Python
浅谈html5 响应式布局
2014/12/24 HTML / CSS
微信端html5页面调用分享接口示例
2018/03/14 HTML / CSS
荷兰演唱会和体育比赛订票网站:viagogo荷兰
2018/04/08 全球购物
在C语言中"指针和数组等价"到底是什么意思?
2014/03/24 面试题
军训自我鉴定
2014/01/22 职场文书
初三学生个人自我评定
2014/04/06 职场文书
文明工地标语
2014/06/16 职场文书
Nginx实现高可用集群构建(Keepalived+Haproxy+Nginx)
2021/05/27 Servers
dubbo集成zipkin获取Traceid的实现
2021/07/26 Java/Android