js动态计算移动端rem
在做移动端web app的时候,众所周知,移动设备分辨率五花八门,虽然我们可以通过CSS3的media query来实现适配,例如下面这样:
1 html {
2 font-size : 20px;
3 }
4 @media only screen and (min-width: 401px){
5 html {
6 font-size: 25px !important;
7 }
8 }
9 @media only screen and (min-width: 428px){
10 html {
11 font-size: 26.75px !important;
12 }
13 }
14 @media only screen and (min-width: 481px){
15 html {
16 font-size: 30px !important;
17 }
18 }
19 @media only screen and (min-width: 569px){
20 html {
21 font-size: 35px !important;
22 }
23 }
24 @media only screen and (min-width: 641px){
25 html {
26 font-size: 40px !important;
27 }
28 }
但是这种做法并不能适配所有设备,于是就有了实现全适配的JS解决方案,例如下面这样:
1 ;(function (doc, win, undefined) {
2 var docEl = doc.documentElement,
3 resizeEvt = 'orientationchange' in win? 'orientationchange' : 'resize',
4 recalc = function () {
5 var clientWidth = docEl.clientWidth;
6 if (clientWidth === undefined) return;
7 docEl.style.fontSize = 20 * (clientWidth / 320) + 'px';
8 };
9 if (doc.addEventListener === undefined) return;
10 win.addEventListener(resizeEvt, recalc, false);
11 doc.addEventListener('DOMContentLoaded', recalc, false)
12 })(document, window);
13
另外附上淘宝移动端适配解决方案flexible.js源码:
1 ;(function(win, lib) {
2 var doc = win.document;
3 var docEl = doc.documentElement;
4 var metaEl = doc.querySelector('meta[name="viewport"]');
5 var flexibleEl = doc.querySelector('meta[name="flexible"]');
6 var dpr = 0;
7 var scale = 0;
8 var tid;
9 var flexible = lib.flexible || (lib.flexible = {});
10
11 if (metaEl) {
12 //将根据已有的meta标签来设置缩放比例
13 var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
14 if (match) {
15 scale = parseFloat(match[1]);
16 dpr = parseInt(1 / scale);
17 }
18 } else if (flexibleEl) {
19 var content = flexibleEl.getAttribute('content');
20 if (content) {
21 var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
22 var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
23 if (initialDpr) {
24 dpr = parseFloat(initialDpr[1]);
25 scale = parseFloat((1 / dpr).toFixed(2));
26 }
27 if (maximumDpr) {
28 dpr = parseFloat(maximumDpr[1]);
29 scale = parseFloat((1 / dpr).toFixed(2));
30 }
31 }
32 }
33
34 if (!dpr && !scale) {
35 var isAndroid = win.navigator.appVersion.match(/android/gi);
36 var isIPhone = win.navigator.appVersion.match(/iphone/gi);
37 var devicePixelRatio = win.devicePixelRatio;
38 if (isIPhone) {
39 // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
40 if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
41 dpr = 3;
42 } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
43 dpr = 2;
44 } else {
45 dpr = 1;
46 }
47 } else {
48 // 其他设备下,仍旧使用1倍的方案
49 dpr = 1;
50 }
51 scale = 1 / dpr;
52 }
53
54 docEl.setAttribute('data-dpr', dpr);
55 if (!metaEl) {
56 metaEl = doc.createElement('meta');
57 metaEl.setAttribute('name', 'viewport');
58 metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
59 if (docEl.firstElementChild) {
60 docEl.firstElementChild.appendChild(metaEl);
61 } else {
62 var wrap = doc.createElement('div');
63 wrap.appendChild(metaEl);
64 doc.write(wrap.innerHTML);
65 }
66 }
67
68 function refreshRem(){
69 var width = docEl.getBoundingClientRect().width;
70 if (width / dpr > 540) {
71 width = 540 * dpr;
72 }
73 var rem = width / 10;
74 docEl.style.fontSize = rem + 'px';
75 flexible.rem = win.rem = rem;
76 }
77
78 win.addEventListener('resize', function() {
79 clearTimeout(tid);
80 tid = setTimeout(refreshRem, 300);
81 }, false);
82 win.addEventListener('pageshow', function(e) {
83 if (e.persisted) {
84 clearTimeout(tid);
85 tid = setTimeout(refreshRem, 300);
86 }
87 }, false);
88
89 if (doc.readyState === 'complete') {
90 doc.body.style.fontSize = 12 * dpr + 'px';
91 } else {
92 doc.addEventListener('DOMContentLoaded', function(e) {
93 doc.body.style.fontSize = 12 * dpr + 'px';
94 }, false);
95 }
96
97
98 refreshRem();
99
100 flexible.dpr = win.dpr = dpr;
101 flexible.refreshRem = refreshRem;
102 flexible.rem2px = function(d) {
103 var val = parseFloat(d) * this.rem;
104 if (typeof d === 'string' && d.match(/rem$/)) {
105 val += 'px';
106 }
107 return val;
108 }
109 flexible.px2rem = function(d) {
110 var val = parseFloat(d) / this.rem;
111 if (typeof d === 'string' && d.match(/px$/)) {
112 val += 'rem';
113 }
114 return val;
115 }
116
117 })(window, window['lib'] || (window['lib'] = {}));
1 ;(function(win, lib) {
2 var doc = win.document;
3 var docEl = doc.documentElement;
4 var metaEl = doc.querySelector('meta[name="viewport"]');
5 var flexibleEl = doc.querySelector('meta[name="flexible"]');
6 var dpr = 0;
7 var scale = 0;
8 var tid;
9 var flexible = lib.flexible || (lib.flexible = {});
10
11 if (metaEl) {
12 //将根据已有的meta标签来设置缩放比例
13 var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
14 if (match) {
15 scale = parseFloat(match[1]);
16 dpr = parseInt(1 / scale);
17 }
18 } else if (flexibleEl) {
19 var content = flexibleEl.getAttribute('content');
20 if (content) {
21 var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
22 var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
23 if (initialDpr) {
24 dpr = parseFloat(initialDpr[1]);
25 scale = parseFloat((1 / dpr).toFixed(2));
26 }
27 if (maximumDpr) {
28 dpr = parseFloat(maximumDpr[1]);
29 scale = parseFloat((1 / dpr).toFixed(2));
30 }
31 }
32 }
33
34 if (!dpr && !scale) {
35 var isAndroid = win.navigator.appVersion.match(/android/gi);
36 var isIPhone = win.navigator.appVersion.match(/iphone/gi);
37 var devicePixelRatio = win.devicePixelRatio;
38 if (isIPhone) {
39 // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
40 if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
41 dpr = 3;
42 } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
43 dpr = 2;
44 } else {
45 dpr = 1;
46 }
47 } else {
48 // 其他设备下,仍旧使用1倍的方案
49 dpr = 1;
50 }
51 scale = 1 / dpr;
52 }
53
54 docEl.setAttribute('data-dpr', dpr);
55 if (!metaEl) {
56 metaEl = doc.createElement('meta');
57 metaEl.setAttribute('name', 'viewport');
58 metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
59 if (docEl.firstElementChild) {
60 docEl.firstElementChild.appendChild(metaEl);
61 } else {
62 var wrap = doc.createElement('div');
63 wrap.appendChild(metaEl);
64 doc.write(wrap.innerHTML);
65 }
66 }
67
68 function refreshRem(){
69 var width = docEl.getBoundingClientRect().width;
70 if (width / dpr > 540) {
71 width = 540 * dpr;
72 }
73 var rem = width / 10;
74 docEl.style.fontSize = rem + 'px';
75 flexible.rem = win.rem = rem;
76 }
77
78 win.addEventListener('resize', function() {
79 clearTimeout(tid);
80 tid = setTimeout(refreshRem, 300);
81 }, false);
82 win.addEventListener('pageshow', function(e) {
83 if (e.persisted) {
84 clearTimeout(tid);
85 tid = setTimeout(refreshRem, 300);
86 }
87 }, false);
88
89 if (doc.readyState === 'complete') {
90 doc.body.style.fontSize = 12 * dpr + 'px';
91 } else {
92 doc.addEventListener('DOMContentLoaded', function(e) {
93 doc.body.style.fontSize = 12 * dpr + 'px';
94 }, false);
95 }
96
97
98 refreshRem();
99
100 flexible.dpr = win.dpr = dpr;
101 flexible.refreshRem = refreshRem;
102 flexible.rem2px = function(d) {
103 var val = parseFloat(d) * this.rem;
104 if (typeof d === 'string' && d.match(/rem$/)) {
105 val += 'px';
106 }
107 return val;
108 }
109 flexible.px2rem = function(d) {
110 var val = parseFloat(d) / this.rem;
111 if (typeof d === 'string' && d.match(/px$/)) {
112 val += 'rem';
113 }
114 return val;
115 }
116
117 })(window, window['lib'] || (window['lib'] = {}));


浙公网安备 33010602011771号