【设计方案】设计方案系列--如何设计移动端高清方案

1、前言

有时候须要前端作到移动端高清显示,一、面对开发移动端H5页面,二、面对不一样分辨率的手机,三、面对不一样屏幕尺寸的手机。javascript

2、视觉稿

前端开发正常是,视觉的小哥哥给咱们psd或者导出的skech文件,这个就是视觉稿,而后前端开始写结构,写元素,调整,优化等等。css

对于移动端开发而言,达到页面高清的效果,视觉稿的规范每每会遵循这两点:html

(1)选取一款手机的屏幕宽高做为基准(之前是iphone4的320480,如今更多的是iphone6的375667)。前端

(2)对于retina屏幕(能够将更多的像素点压缩至一块屏幕里,从而达到更高的分辨率并提升屏幕显示的细腻程度)(如:dpr=2),为了达到高清效果,视觉稿的画布大小会是基准的2倍,也就是说像素点个数是原来的4倍(好比iphone6的,原先的375667,就会变成7501334)。java

确定有疑问:(1)为啥dpr=2的手机,为何画布大小*2,就能够解决高清问题?(2)对于2倍大小的视觉稿,具体的css是如何还原每个区块的真实宽高(布局问题)?android

3、基础概念

一、物理像素

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

二、设备独立像素

设备独立像素也叫与密度无关像素,能够认为是计算机坐标系统中获得一个点,这个点表明一个能够由程序使用的虚拟像素(好比:css像素),而后由相关系统转换为物理像素。web

因此,物理像素和设备独立像素之间存在必定的对应关系,这就是要说的设备像素比。算法

三、设备像素比

设备像素比(简称为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)。

四、举个例子

以iphone6为例:

(1)设备宽高为375*667,能够理解成设备的独立像素(css像素);

(2)dpr为2,根据上面计算公式,物理像素应该就是750*1334。

用一张图来表现,就是这样(原谅个人盗图):

image

在不一样的屏幕上(普通屏幕 vs retina屏幕),css像素所呈现的大小是一致的,不一样的是1个css像素所对应的物理像素个数是不一致的。

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

五、位图像素

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

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

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

看一张图:

image

如图所示:对于dpr=2的retina屏幕而言,1个位图像素对于4个物理像素,因为单个位图像像素不能够在分隔,只能就近取色,从而致使图片模糊。

因此对于图片高清的问题,比较好的方案是两倍图片(长宽增大到2倍)。

如:200×300(css pixel)img标签,就须要提供400×600的图片。

如此下来,位像素点个数就是原来的4倍,在retina屏幕下,位图像素点个数就能够跟物理像素点个数造成1:1的比例,图片天然就清晰了,解决了第一个疑问。

若是出现,普通屏幕下,也用了两倍图片,会怎么样?

很明显,在普通屏幕下,200×300(css pixel)img标签,所对应的物理像素个数就是200×300个,而两倍图片的位图像素个数则是200×300*4,因此就出现1个物理像素点对应4个位图像素点,它的取色也只能经过必定的算法(显示结果就是一张只有原图像素总数四分之一,咱们称这个过程叫作downsampling(降采样,下降数据采样率或分辨率的过程)).肉眼看上去虽然图片不会模糊,可是会以为图片缺乏一些锐利度,或者是有点色差(但仍是能够接受的)。

4、总结

移动端H5开发,在不一样的分辨率,不一样屏幕的手机下会遇到几个经典问题

一、retina下,图片高清的问题

上面已经讲到了解决方案:图片的长宽的两倍,而后图片容器缩小50%。

好比:

一、img 标签

width: 200px;
height: 300px;
二、背景图片

width: 200px;
height: 300px;
background-image: url(image@2x.jpg);
background-size: 200px 300px; // 或者: background-size: contain;
这样的缺点就是,普通屏幕下:

一、一样下载长度都2倍的图片,形成了资源浪费。

二、图片因为downSampling,会失去一些锐利度(或者色差)。

因此最好的解决办法:不一样的dpr下,加载不一样的尺寸的图片。

不论是经过css媒体查询,仍是经过js条件判断都是能够的。因此须要准备两套图片。

二、retina下,border:1px的问题

1px是设计师用他的像素眼,最关心的问题。

仍是经过一张图来解释(原谅我再次盗图):

image

上图中,对于一条1px宽的直线,它们在屏幕上的物理尺寸(灰色区域)的确是相同的,不一样的实际上是屏幕上最小的物理显示单元,即物理像素,因此对于一条直线,iphone5它能显示的最小宽度实际上是图中的红线圈出来的灰色区域,用css来表示,理论上说是0.5px。

因此,设计师想要的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;
}

咱们照常写border-bottom: 1px solid #ddd;,而后经过transform: scaleY(.5)缩小0.5倍来达到0.5px的效果,可是这样hack实在是不够通用(如:圆角等),写起来也麻烦。

或者可使用js来判断当前浏览器是否支持border的0.5px,若是支持就会在HTML上添加一个class名hairlines,

if (window.devicePixelRatio && devicePixelRatio >= 2) {
  var testElem = document.createElement('div');
  testElem.style.border = '.5px solid transparent';
  document.body.appendChild(testElem);
  if (testElem.offsetHeight == 1)
  {
    document.querySelector('html').classList.add('hairlines');
  }
  document.body.removeChild(testElem);
}

css

div {
  border: 1px solid #bbb;
}
 
.hairlines div {
  border-width: 0.5px;
}

5、参考

一、http://www.smashingmagazine.c...

二、http://www.paintcodeapp.com/n...

三、http://iconmoon.com/blog2/iph...

四、http://dieulot.net/css-retina...

相关文章
相关标签/搜索