web 页面做移动端适配, 就是在不同尺寸的手机设备上, 页面 "相对性的达到合理的展示(自适应)" 或者 "保持统一效果的等比缩放(看起来差不多)". 有几个要点必须要掌握, 一个是不同尺寸, 一个是清晰, 还有一个是合理. 为什么强调这几个词当然是有原因的.
一, 目标
1. 页面布局总是按照一定规则来进行的. 但是移动设备却是多种多样的, 屏幕尺寸大小不同, 分辨率不同, 像素比不同, 宽高也不同(相应的概念会在后面介绍). 所以要让一套代码适应所有设备, 是最棘手的.,
2. 要保证清晰度, 小屏手机和大屏手机用同样的图片, 通过缩放效果显示的大小比例是一致的, 但是图片放大会失真, 高清图缩小预览又浪费. 这就需要综合考虑情况了.
3. 所谓合理展示, 指的是不论什么设备都能有原设计稿一样的视觉和体验效果. 如果单纯的按照固定的像素 px 来设置宽高, 结果会怎样. 要么小屏手机出现滚动条, 要么大屏手机有留白. 虽说是原样输出, 但这并不是设计稿的效果. 人家设计稿是全屏完美展示, 不能到手机上变成半屏或两屏了. 所以说还原设计稿可以理解成等比例缩放.
二, 思考
我们的目的搞清楚了, 但是还是不得不先泼一泼冷水. 首先, 没有绝对完美的适配方案. 不可能让所有设备真正 100% 还原设计稿. 因为设备的宽高比例就不尽相同五花八门, 光这一点就没办法解决, 比如说你想用同一张图片给正方形和长方形做壁纸, 总有一个会被拉伸或是留白. 所以目前通用的原则是文字流式, 控件弹性, 图片等比缩放. 借用万能网络上图片展示下效果.
有了目标和大致想法接下来差不多上方案了, 为了更好讲解, 还得科普几个知识点.
三, 基本概念
屏幕尺寸(inch): 手机设备的对角线长度, 比如 iphone5 为 4 英寸.
屏幕宽高比: 手机的高度与宽度的比例 为 16:9
物理像素 (px): 显示器(手机屏幕) 上最小的物理显示单元, 比如 iphone5 的物理像素是 640*1136
像素密度 (PPI): 表示沿着对角线, 每英寸所拥有的物理像素(Pixel) 数目, 值越低颗粒感越强, 超过 300 人眼很难分辨
设备独立像素 | 密度无关像素 | 逻辑像素(px): 可以认为是计算机坐标系统中得一个点, 这个点代表一个可以由程序使用的虚拟像素(比如: CSS 像素), 然后由相关系统转换为物理像素. 比如 iphone5 的物理像素是 320*568
像素比(pdr): 物理像素和设备独立像素的对应关系, 设备像素比 = 物理像素 / 设备独立像素, 比如 iphone5 的像素比是 2.
以上概念如果一下接受不了自行百度吧. 在这里主要解释下 pdr, 原来的显示设备的 pdr 都是 1, 后来引入了高清屏有了 retina, 这个 pdr 就出现了. 当然是值越高, 显示效果越清楚, 同时意味着用 css 控制某个像素的时候, 实际上控制的是成倍的物理像素. 最简单的例子是用 Iphone5 截个图, 虽然 css 下最宽只有 320px, 但是把图片放到电脑上就成了 640px 了.
四, 深入了解适配下的高清问题
用多大的图片才能清晰?
如果在 pdr 为 1 的情况下, 要显示 100*100 的图片, 用 50*50,100*100 还是 200*200 的图片. 当然我们都能理解 50*50 肯定是要排除的. 不过, 原因是什么我们还需要讨论一下. 换个更形象的说法, 要用要求的红黄颜料填满 2 个坑, 是要用一种颜料还是 2 种还是 4 种. 如果用一种颜料同时显示红与黄的效果, 那么只能把两种颜料先混合再倒入, 结果肯定会失真; 如果用两种, 分别用红和黄倒入, 那么就泾渭分明; 如果用 4 种呢, 就得压缩一半塞进去, 也就是说红和黄已经被压缩了一半, 还会渗进其它颜色才填满. 这个时侯, 显示效果会失去锐度. 所以不论给的图片大了还是小了都不会模糊.
但是好多设备不是单单的 pdr 为 1, 如果等于 2 的时候, 要显示 100*100 的图片, 就需要 200*200 的图片; 如果 pdr 为 3, 就要引入 300*300 的图片, 同样有更多像素比的设备, 不可能一一满足, 因此普通做法是提供 2x,3x 图片.
五, 适配方案
终于要讲到方案了, 上面也讲到了要实现自适应就是等比例缩放. 因此我们想到三种方案.
一, 按百分比设置宽高. 可能实现适配效果, 缺点是会出现拉伸, 模糊, 因为设备宽高比不同, 高度很难用百分比控制.
二, viewport 缩放
在页面内可以设置 viewport 的 scale
属性来控制页面显示比例. 类似于放大缩小图片, 通过计算设备宽度与设计稿的比例来得出缩放的倍数, 最终实现适配效果. 为了适配大多数设备并保证清晰度要采用更大分辨率的设计稿, 感觉有些浪费资源.
三, rem 相对单位
因为 rem 是相对单位, 它会以 Htm 的 font-size 的大小为基数来计量长度. 所以计算设备屏幕宽度与设计稿的比例来动态设备 html 的 font-size,. 这样就能在不同设备上等比例来显示. 相当于先把屏幕宽度等分成固定的份数, 然后再以份数作为单位计量.
其实现在的适配方案不外乎这么几种, 尤其第三种操作起来很方便(后面会附上代码). 不过, 阿里团队为了追求清晰度和解决 1px 的问题又推出了高清适配方案, 主要是把像素比考虑进去, 结合第二种第三种方案来实现. 方法是先用设备宽度与 pdr 相乘然后取到与设计稿的比例, 动态设置 html 的 font-size, 最后再根据 pdr 的值动态设置 scale 来实现缩放.
备注: 1px 问题指的是在使用 rem 后, 会出现像素值为小数的情况, 小数位可能会被系统直接忽略掉, 出现宽窄不同的现象.
附普通适配方案(代码摘自网络):
<script type="text/javascript">
new function (){
var _self = this;
_self.width =1080;// 设置 UI 提供的基准尺寸
_self.fontSize = 200;// 默认字体大小, 使用时除以此参数作为 rem, 建议取 10 或 100 容易计算. 为保证谷歌良好适配, 320/_self.width*_self.fontSize>12
_self.widthProportion = function(){
var p = (document.body&&
document.body.clientWidth ||
document.getElementsByTagName("html")[0].offsetWidth)/_self.width;
return p>0.71?0.71:(p<0.3?0.3:p); // 设置安全尺寸最宽 768px, 最小 320px
};
console.log(_self.widthProportion());
_self.changePage = function(){
document.getElementsByTagName("html")[0].setAttribute("style","font-size:"+_self.widthProportion()*_self.fontSize+"px !important");
}
_self.changePage();
window.addEventListener("resize",function(){_self.changePage();},false);
};
</script>
高清适配方案(代码摘自网络):
<script>
(function(doc, win, designSize) { //designSize 为设计稿的尺寸(宽)
var docEl = document.documentElement,
devWidth = docEl.clientWidth> 1080 ? 1080 : docEl.clientWidth,
dpr = devicePixelRatio || 1,
scale = 1 / dpr,
width = dpr * devWidth,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'onresize', // 判断横屏和窗口重置
recalc = function() {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
document.querySelector('meta[name="viewport"]') .setAttribute('content','width=' + width + ',
initial-scale='+ scale +', maximum-scale='+ scale +', minimum-scale='+ scale +', user-scalable=no');
docEl.style.fontSize = devWidth / (designSize / 100) * dpr + 'px';
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window, 750);
</script>
参考文章:
- https://segmentfault.com/a/1190000008767416
- http://www.aliued.com/?p=3166
- https://www.jianshu.com/p/07669cb3e7c5
来源: https://www.cnblogs.com/zuoshoupai/p/9538068.html