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 相关文章推荐
在线编辑器的实现原理(兼容IE和FireFox)
Mar 09 Javascript
一个符号插入器 中用到的js代码
Sep 04 Javascript
JS Excel读取和写入操作(模板操作)实现代码
Apr 11 Javascript
左侧是表头的JS表格控件(自写,网上没有的)
Jun 04 Javascript
原生JS操作网页给p元素添加onclick事件及表格隔行变色
Dec 01 Javascript
JavaScript表格常用操作方法汇总
Apr 15 Javascript
JS实现网站菜单拖拽移位效果的方法
Sep 24 Javascript
正则表达式替换html元素属性的方法
Nov 26 Javascript
详解Node中导入模块require和import的区别
Aug 11 Javascript
Node.js readline模块与util模块的使用
Mar 01 Javascript
浅谈实现在线预览PDF的几种解决办法
Aug 10 Javascript
Vue2.x-使用防抖以及节流的示例
Mar 02 Vue.js
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取得一个类的属性和方法的实现代码
2011/05/22 PHP
PHP调用Linux的命令行执行文件压缩命令
2013/01/27 PHP
PHP发送短信代码分享
2015/08/11 PHP
CentOS7编译安装php7.1的教程详解
2019/04/18 PHP
php 使用ActiveMQ发送消息,与处理消息操作示例
2020/02/23 PHP
Swoole扩展的6种模式深入详解
2021/03/04 PHP
通过ifame指向的页面高度调整iframe的高度
2006/10/05 Javascript
js 数组操作代码集锦
2009/04/28 Javascript
javascript 写类方式之六
2009/07/05 Javascript
JavaScript.The.Good.Parts阅读笔记(二)作用域&amp;闭包&amp;减缓全局空间污染
2010/11/16 Javascript
JavaScript中Math对象方法使用概述
2014/01/02 Javascript
一行命令搞定node.js 版本升级
2014/07/20 Javascript
JavaScript仿静态分页实现方法
2015/08/04 Javascript
javascript实现base64 md5 sha1 密码加密
2015/09/09 Javascript
javascript实现鼠标点击页面 移动DIV
2016/12/02 Javascript
微信小程序 wx.uploadFile在安卓手机上面the same task is working问题解决
2016/12/14 Javascript
jQuery+HTML5实现WebGL高性能烟花绽放动画效果【附demo源码下载】
2017/08/18 jQuery
微信小程序如何获取用户手机号
2018/01/26 Javascript
vue 实现边输入边搜索功能的实例讲解
2018/09/16 Javascript
Node.js fs模块(文件模块)创建、删除目录(文件)读取写入文件流的方法
2019/09/03 Javascript
nodejs中使用archive压缩文件的实现代码
2019/11/26 NodeJs
vue使用微信扫一扫功能的实现代码
2020/04/11 Javascript
纯JS实现五子棋游戏
2020/05/28 Javascript
React实现评论的添加和删除
2020/10/20 Javascript
python生成验证码图片代码分享
2016/01/28 Python
Python提取频域特征知识点浅析
2019/03/04 Python
python实现各种插值法(数值分析)
2019/07/30 Python
Python任务自动化工具tox使用教程
2020/03/17 Python
Django实现文章详情页面跳转代码实例
2020/09/16 Python
python 爬虫如何正确的使用cookie
2020/10/27 Python
澳大利亚药房在线:ThePharmacy
2017/10/04 全球购物
英国领先的票务代理商之一:The Ticket Factory
2019/02/09 全球购物
2014党员民主评议个人总结
2014/09/10 职场文书
实训报告范文大全
2014/11/04 职场文书
2014年法院个人工作总结
2014/12/17 职场文书
2015年销售助理工作总结
2015/05/11 职场文书