移动端屏幕适配解决方案

worldly1013 worldly1013     2022-08-12     646

关键词:

  因原在做移动端适配过程中,一直都是应用淘宝的flexible高清方案解决,也没有认真的去研究过源码。这几天又看到一些普通的适配方案,于是把两者源码放在一起比较,发现高清方案是通过动态的获取了当前设备的dpr值,然后根据dpr值的大小来设定手机的视口的缩放比例,从而实现高清。比如:dpr=2时,设定initial-scale = 0.5 ;  dpr=3时 ,设定initial-scale = 0.333 ;

一、手机端viewport详解

 <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1,maximum-scale=1">

1.因原手机端厂商为了使电脑端页面更好的迁移到手机端上来,因此大部分手机默认将viewport设为980px ,因此我们在写手机端页面时,上来通常会加上这样一句<meta>声明,这句话究竟有什么用了,又是什么意思了?

width:控制 viewport 的大小,可以指定的一个值或者特殊的值,如 device-width 为设备的宽度(单位为缩放为 100% 时的 CSS 的像素)。

initial-scale:初始缩放。即页面初始缩放程度。这是一个浮点值,是页面大小的一个乘数。例如,如果你设置初始缩放为“1.0”,那么,web页面在展现的时候就会以target density分辨率的1:1来展现。如果你设置为“2.0”,那么这个页面就会放大为2倍。

maximum-scale:最大缩放。即允许的最大缩放程度。这也是一个浮点值,用以指出页面大小与屏幕大小相比的最大乘数。例如,如果你将这个值设置为“2.0”,那么这个页面与target size相比,最多能放大2倍。

minimum-scale:最小缩放,即允许的最小缩放程度。

二、普通方案

代码如下:

 1 var docEl=document.documentElement;
 2 var win=window;
 3 function refreshRem(){
 4     //获取元素宽度
 5     var width=docEl.getBoundingClientRect().width;
 6     console.log(width);
 7     //以640的设计稿为基准,
 8     //直接用设计稿尺寸除以100即得到相对单位rem的值.
 9     var rem=width/640*100;
10     docEl.style.fontSize=rem+'px';
11 }
12 var temp;
13 //监听浏览器窗口改变大小事件
14 win.addEventListener('resize',function(){
15     clearTimeout(temp);
16     temp=setTimeout(refreshRem,300);
17 },false);
18 //监听浏览网页事件
19 win.addEventListener('pageshow',function(e){
20     if(e.persisted){
21         clearTimeout(temp);
22         temp=setTimeout(refreshRem,300);
23     }
24 },false);
25 //初始化
26 refreshRem();

   该JS文件通过获取设备当前宽度,然后通过设定 rem = width / 640  *  100 ;  从而动态的设定rem值的大小,然后把html根节点的font-size大小设为1rem值所代表的字体大小,然后我们就可以愉快

的使用rem来进行移动端的布局了。当然这是针对640px基本设计稿的(iphone5), 如果你使用的是750px的设计稿(iphone6),改为 rem = width/750 * 100 就好了,即本文代码中蓝色标记部分

  注意:html文件开头时需要加上此句meta声明

  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1,minimum-scale=1,maximum-scale=1" />

三、高清方案

代码如下:

  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         console.warn('将根据已有的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 / 640 * 100;
 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'] = {}));

 

  该JS文件做了上述文件的工作并根据设备当前的dpr值动态的缩放了手机的视口,即dpr=2时,设定initial-scale = 0.5 ;  dpr=3时 ,设定initial-scale = 0.333 ;从而有效的实现了高清方案。其适配

方法与上述一样,你也可以根据你设计师妹妹给你的设计稿情况动态的设定rem的大小,怎么方便怎么来,权利完全在你手上,你可是能够改变世界的人哦!!!

  注意:此法不需要在html文件开头在写 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1,minimum-scale=1,maximum-scale=1" /> 这个声明,不然它

会按照你写的meta声明来对视口进行管理,从而不会再自动对视口进行缩放(代码请看源码蓝色标记)。

  

此法优点:

1.能够有效解决边框1px问题

2.能够很好的使图片达到适配

 

四、rem单位转换工具

1、使用sass预处理器

@function px2em($px, $base-font-size: 16px) {
  @if (unitless($px)) {
    @warn "Assuming #{$px} to be in pixels, attempting to convert it into pixels for you";
    @return px2em($px + 0px); // That may fail.
  } @else if (unit($px) == em) {
    @return $px;
  }
  @return ($px / $base-font-size) * 1em;
}

 

2、使用CSSREM插件

一个CSS的px值转rem值的Sublime Text 3自动完成插件

效果如下:

 

下载地址:CSSREM插件下载地址

使用方法详见MD文件,默认设置为1rem = 40px ;

 

 

 

 

 

 

08-移动端开发教程-移动端适配方案

...字体水平百分比布局水平方向部分也可以使用弹性布局Rem解决方案Rem的大小取值:根据页面的dpr动态改变Rem的取值:1rem=100px或者1rem=1/10*理想视口的宽度chrome浏览器 查看详情

原创移动端高清多屏适配方案

 移动端高清、多屏适配方案背景开发移动端H5页面面对不同分辨率的手机面对不同屏幕尺寸的手机视觉稿在前端开发之前,视觉MM会给我们一个psd文件,称之为视觉稿。对于移动端开发而言,为了做到页面高清的效果,视觉... 查看详情

移动端屏幕适配原理以及方法讲解

序言:今天周日,我正坐在黄埔区图书馆,思索着关于移动端屏幕适配的问题。作为一名年纪轻轻的前端马蓉,不,是码农,移动端屏幕适配的方案的帖子没读过100篇吧,也读过几十篇了。可是今天我又在思考这个问题了,因为... 查看详情

移动端高清多屏适配方案

背景开发移动端H5页面面对不同分辨率的手机面对不同屏幕尺寸的手机视觉稿在前端开发之前,视觉MM会给我们一个psd文件,称之为视觉稿。对于移动端开发而言,为了做到页面高清的效果,视觉稿的规范往往会遵循以下两点:1... 查看详情

移动端高清多屏适配方案

背景开发移动端H5页面面对不同分辨率的手机面对不同屏幕尺寸的手机视觉稿在前端开发之前,视觉MM会给我们一个psd文件,称之为视觉稿。对于移动端开发而言,为了做到页面高清的效果,视觉稿的规范往往会遵循以下两点:... 查看详情

移动端适配方案(代码片段)

首先,我们需要知道rem和em的基本概念。rem:相对于html根元素的fontsize。em:相对于当前元素的字体大小。rem和em都能够根据屏幕大小做适配。 一、假设现在给出我们一张750px的设计图,我们在设计图上量出200px*200px的div大小,并... 查看详情

移动端主流适配方案

1、流式布局(百分比布局)  案例:京东移动端优点:简单方便,只需要固定高度,宽度自适应;缺点:大屏幕手机实际显示的不协调。2、响应式布局优点:可以节约成本,不用再做专门的webapp网站(外包公司、小公司... 查看详情

移动端高清屏适配方案

结论:用户体验要求很高的页面,如UV较高的页面,活动页这些应该以用户体验优先,应用flexiable方案在其它页面,固定视口,不缩放,使用rem做布局适配,js添加屏幕标识以便调整字体大小(即布局使用rem,字体使用百分比)... 查看详情

移动端界面的适配

...适配中背景图片的处理适配的原理解析 摘要:在进行移动端界面的书写的时候,如果把宽度高度或者字体大小全部写死的话,那么在所有手机上看到的大小都一样,存在的问题就是同样大小的字体,或者一个盒子模型,在大... 查看详情

移动端前端适配方案20170707

1.MeidaQueriesmeidaqueries 的方式可以说是我早期采用的布局方式,它主要是通过查询设备的宽度来执行不同的 css 代码,最终达到界面的配置。核心语法是:@mediascreenand(max-width:600px){/*当屏幕尺寸小于600px时,应用下面的CSS... 查看详情

移动端适配方案以及rem和px之间的转换

背景开发移动端H5页面面对不同分辨率的手机面对不同屏幕尺寸的手机视觉稿在前端开发之前,视觉MM会给我们一个psd文件,称之为视觉稿。对于移动端开发而言,为了做到页面高清的效果,视觉稿的规范往往会遵循以下两点:1... 查看详情

移动端适配方案-rem(基础篇)

    常见移动web适配方案一般有3种方法,如下图:      ①:定高,宽度百分比(百分比适配简单,一般用来做一些适配性不高的页面,比如只有一些文字和图片等简单的屏幕适配)    ②:flex(更多的用于复... 查看详情

移动端font-size适配方案(续)

概述之前写过一篇移动端font-size适配方案,但是在实践过程中,还是发现当时的思维太局限了,视野太窄了,所以现在补充更新一下,记录下来,供以后开发时参考,相信对其他人也有用。我上一篇博文主要有2个误区,下面我... 查看详情

移动端适配方案:js实现动态改变根元素的字体大小

参考技术A通过js动态获取屏幕的宽度(document.clientWidth)然后根据屏幕宽度动态计算出rem的实际值。假设,640px的设备1rem=100px公式:rem=document.clientWidth/640*100px; 查看详情

移动端界面适配

...://www.cnblogs.com/xianyulaodi/p/5533201.html  摘要:在进行移动端界面的书写的时候,如果把宽度高度或者字体大小全部写死的话,那么在所有手机上看到的大小都一样,存在的问题就是同样大小的字体,或者一个盒子模型,在大... 查看详情

手淘h5移动端适配方案flexible源码分析(代码片段)

移动端适配一直是一个值得探讨的问题,在业余时间我找了一些页面,查看了一些厂商对于移动端H5页面的适配方案,看到了几个典型的例子,今天就来记录一下我看到的第一个典型的例子,也是我们公司目前普通H5项目正在使... 查看详情

移动端适配方案(代码片段)

还原设计稿,也就是如何适配移动端繁杂的屏幕大小。通常而言,设计师只会给出单一分辨率下的设计稿,而我们要做的,就是以这个设计稿为基准,去适配所有不同大小的移动端设备。在此之前,有一些基础概念需要理解。设... 查看详情

flutter学习-屏幕适配(代码片段)

...设备相关信息2.适配方案2.1常用的适配方案2.2rpx适配目前移动端设备非常多,并且不同的设备手机屏幕也不相同。目前做移动端开发都要针对不同的设备进行一定的匹配,无论是移动原生开发、小程序、H5页面那么下面我... 查看详情