<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">步骤2:
div{ width: 2rem; height: 3rem;}通过上面的3个步骤,我们就可以将我们的移动端页面做成适配的了。
;(function(win, lib) { var doc = win.document; var docEl = doc.documentElement; var metaEl = doc.querySelector("meta[name="viewport"]"); var flexibleEl = doc.querySelector("meta[name="flexible"]"); var dpr = 0; var scale = 0; var tid; var flexible = lib.flexible || (lib.flexible = {}); if (metaEl) {console.warn("将根据已有的meta标签来设置缩放比例");var match = metaEl.getAttribute("content").match(/initial-scale=([d.]+)/);if (match) { scale = parseFloat(match[1]); dpr = parseInt(1 / scale);} } else if (flexibleEl) {var content = flexibleEl.getAttribute("content");if (content) { var initialDpr = content.match(/initial-dpr=([d.]+)/); var maximumDpr = content.match(/maximum-dpr=([d.]+)/); if (initialDpr) {dpr = parseFloat(initialDpr[1]);scale = parseFloat((1 / dpr).toFixed(2));} if (maximumDpr) {dpr = parseFloat(maximumDpr[1]);scale = parseFloat((1 / dpr).toFixed(2));}} } if (!dpr && !scale) {var isAndroid = win.navigator.appVersion.match(/android/gi);var isIPhone = win.navigator.appVersion.match(/iphone/gi);var devicePixelRatio = win.devicePixelRatio;if (isIPhone) { // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案 if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {dpr = 3; } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){dpr = 2; } else {dpr = 1; }} else { // 其他设备下,仍旧使用1倍的方案 dpr = 1;}scale = 1 / dpr; } //为html标签添加data-dpr属性 docEl.setAttribute("data-dpr", dpr); if (!metaEl) {metaEl = doc.createElement("meta");metaEl.setAttribute("name", "viewport");// 动态设置meta metaEl.setAttribute("content", "initial-scale=" + scale + ", maximum-scale=" + scale + ", minimum-scale=" + scale + ", user-scalable=no");if (docEl.firstElementChild) { docEl.firstElementChild.appendChild(metaEl);} else { var wrap = doc.createElement("div"); wrap.appendChild(metaEl); doc.write(wrap.innerHTML);} } //根据dpr和物理像素设置rem function refreshRem(){//getBoundingClientRect().width相当于物理像素var width = docEl.getBoundingClientRect().width;// width / dpr > 540等于独立像素if (width / dpr > 540) { width = 540 * dpr;}var rem = width / 10; // 将屏幕宽度分成10份, 1份为1rem. rem转化px计算公式=d*(width/10)docEl.style.fontSize = rem + "px";flexible.rem = win.rem = rem; } // 监听窗口变化,重新设置尺寸 win.addEventListener("resize", function() {clearTimeout(tid);tid = setTimeout(refreshRem, 300); }, false); // 当重新载入页面时,判断是否是缓存,如果是缓存,执行refreshRem() win.addEventListener("pageshow", function(e) {if (e.persisted) { clearTimeout(tid); tid = setTimeout(refreshRem, 300);} }, false); if (doc.readyState === "complete") {doc.body.style.fontSize = 12 * dpr + "px"; } else {doc.addEventListener("DOMContentLoaded", function(e) { doc.body.style.fontSize = 12 * dpr + "px";}, false); } refreshRem(); flexible.dpr = win.dpr = dpr; flexible.refreshRem = refreshRem; flexible.rem2px = function(d) {var val = parseFloat(d) * this.rem;if (typeof d === "string" && d.match(/rem$/)) { val += "px";}return val; } flexible.px2rem = function(d) {var val = parseFloat(d) / this.rem;if (typeof d === "string" && d.match(/px$/)) { val += "rem";}return val; }})(window, window["lib"] || (window["lib"] = {}));适配中背景图片的处理
假设现在我们要用的那个勋子的背景图。分为以下几步:
1、测量勋字这张背景图的大小,大小为:75px*85px
2、测量这个勋字在雪碧图的位置,也就是设置background-position:.经测量,他在雪碧图的位置为 x:-123px,y:-7px
3、对着张雪碧图进行换算:看下面代码:
知道了上面的尺寸,我们就行换算即可,将每个值除以640再乘以10 为什么这么算,可以看看源码
要使用这样雪碧图:
<!-- 长宽为: -->width: 75/640*10=1.171875rem;height: 85/640*10=1.328125rem;<!-- background-size为 --><!-- 因为整张雪碧图的宽度为200px, -->background-size: 200/640*10rem auto;<!-- background-position为: -->background-position: -123/640*10rem -7/640*10rem;html:
<i class="item1"></i>
.item1{ width: 75/640*10=1.171875rem; height: 85/640*10=1.328125rem; margin: 20px auto; background: url("../images/itemBg.png") no-repeat; // 因为整张雪碧图的宽度为200px, background-size: 200/640*10rem auto; 等于 background-size: 3.125rem auto; // 该背景图在雪碧图的位置 background-position: -123/640*10rem -7/640*10rem; 等于 background-position: -1.921875rem -0.109375rem; display: block;}因为换算比较麻烦,所以建议使用sass或者less来进行计算。具体效果我放在了github上,可以看看:
盗图,哈哈
设备独立像素(density-independent pixel)
设备独立像素(也叫密度无关像素),可以认为是计算机坐标系统中得一个点,这个点代表一个可以由程序使用的虚拟像素(比如: css像素),然后由相关系统转换为物理像素。
所以说,物理像素和设备独立像素之间存在着一定的对应关系,这就是接下来要说的设备像素比。
可以理解为css像素,比如宽度为20px等等。
设备像素比(device pixel ratio ),简称dpr
设备像素比(devicePixelRatio简称dpr)定义了物理像素和设备独立像素的对应关系,它的值可以按如下的公式的得到:
设备像素比 = 物理像素 / 设备独立像素
在javascript中,可以通过window.devicePixelRatio获取当前设备的dpr
css中的px可以看做是设备的独立像素,所以通过devicePixelRatio,我们可以知道该设备上一个css像素代表多少个物理像素。
例如,在Retina屏的iphone上,devicePixelRatio的值为2,也就是说1个css像素相当于2个物理像素。
再举个例子:iphone6中:
设备宽高为375×667,可以理解为设备独立像素(或css像素)。
dpr为2,根据上面的计算公式,其物理像素就应该×2,为750×1334。
是不是有点头晕了,可以看看这篇文章消化一下:http://div.io/topic/1092
理解了上面的概念,就比较好理解它的实现原理了
理解它的原理有两点:
1、了解利用meta标签对viewport进行控制
我们可以看看我们通常在head里面加的meta标签
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1,user-scalable=no">该meta标签的作用是让当前viewport的宽度等于设备的宽度,同时不允许用户手动缩放。
根据不同的像素设备比,来对页面进行不同的缩放。页面缩放的 scale=1/dpr ;
来看移动端淘宝接下来的三张图:https://m.taobao.com/#index
三星galasy S4
data-dpr=1, 所以 initial-scale=1 (因为源码上 scale = 1 / dpr;)
iPhone5:
data-drp=2,所以initial-scale=0.5
iphone 6 Plus
第二个要点:
动态设置html的font-size,html元素的font-size的计算公式,font-size = deviceWidth / 10。我们也可以看到上面三张截图的html里面的font-size是不同的
源码如下:
var width = docEl.getBoundingClientRect().width;if (width / dpr > 540) { width = 540 * dpr;}var rem = width / 10;docEl.style.fontSize = rem + "px";flexible.rem = win.rem = rem;其实flexible的实质就干了以下几件事