溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

移動(dòng)端界面的適配

發(fā)布時(shí)間:2020-08-28 19:45:11 來(lái)源:腳本之家 閱讀:138 作者:咸魚(yú)老弟 欄目:web開(kāi)發(fā)

閱讀目錄

  • 適配的要求
  • 適配的方法,3個(gè)步驟
  • 適配中背景圖片的處理
  • 適配的原理解析

摘要:在進(jìn)行移動(dòng)端界面的書寫的時(shí)候,如果把寬度高度或者字體大小全部寫死的話,那么在所有手機(jī)上看到的大小都一樣,存在的問(wèn)題就是同樣大小的字體,或者一個(gè)盒子模型,

在大屏幕手機(jī)上看起來(lái)會(huì)有點(diǎn)偏小。比如iphone6PLUS。如果是做成適配的話,就很好的解決了這個(gè)問(wèn)題,大屏幕顯示的內(nèi)容大一點(diǎn),小屏幕顯示的小一點(diǎn)。

所以今天做一個(gè)移動(dòng)端頁(yè)面適配的小小總結(jié)

適配的要求

1、在不同分辨率的手機(jī)上,頁(yè)面看起來(lái)是自適應(yīng)的。整體效果看起來(lái)比較和諧。不會(huì)說(shuō)大屏幕上看起來(lái)特別小。小屏幕上看起來(lái)特別大

2、主要是關(guān)注字體,寬高,間距,圖片大小等。

3、所提供的設(shè)計(jì)圖一般是手機(jī)分辨率的兩倍,才能方便做適配。

4、使用rem做單位,而不是傳統(tǒng)的px

適配的方法,3個(gè)步驟

步驟1:

設(shè)置viewport,也就是平時(shí)寫移動(dòng)端頁(yè)面都要加上的:

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

步驟2:

首先我們?cè)谖覀兊捻?yè)面引入下面的flexible.js,

這段適配的js代碼是拿淘寶的來(lái)用的。

適配的js代碼的github地址如下:https://github.com/amfe/lib-flexible/blob/master/src/flexible.js。

步驟3:

頁(yè)面上我們的css代碼可以這樣寫,比如設(shè)計(jì)圖給我們的尺寸是750*1000的。某個(gè)容器在設(shè)計(jì)圖的寬度是150px*225px,那我們?cè)赾ss里面

寬度:150px/750px/10=150px/75px=2rem;

高度為:225px/75px=3rem;

一句話:布局的時(shí)候,各元素的css尺寸=設(shè)計(jì)稿標(biāo)注尺寸/設(shè)計(jì)稿橫向分辨率/10;

div{
 width: 2rem;
 height: 3rem;
}

通過(guò)上面的3個(gè)步驟,我們就可以將我們的移動(dòng)端頁(yè)面做成適配的了。

css換算方法

不過(guò)有一點(diǎn),一直算來(lái)算去挺煩的。所以在寫css的時(shí)候,最好使用css預(yù)處理器,比如sass、less來(lái)寫,這樣就方便很多了。

或者在sublimeText3中安裝cssREM插件,正常書寫px單位,然后編輯器自動(dòng)幫你換算成rem.

cssREM插件的安裝教程:https://github.com/flashlizi/cssrem

注意點(diǎn):

容器的寬度高度我們用rem為單位,但是字體大小font-size我們還是用px,而不是用rem

原因:

flexible.js的作者winter是這樣解釋的:考慮到字體的點(diǎn)陣信息,一般文字尺寸多會(huì)采用 16px 20px 24px等值,若以rem指定文字尺寸,會(huì)產(chǎn)生諸如21px,19px這樣的值,會(huì)導(dǎo)致字形難看,毛刺,甚至黑塊,故大部分文字應(yīng)該以px設(shè)置。

一般標(biāo)題類文字,可能也有要求隨屏幕縮放,且考慮到這類文字一般都比較大,超過(guò)30px的話,也可以用rem設(shè)置字體。

下面粘貼一下flexible.js的源碼:加了注釋

flexible.js

;(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('將根據(jù)已有的meta標(biāo)簽來(lái)設(shè)置縮放比例');
 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下,對(duì)于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 {
  // 其他設(shè)備下,仍舊使用1倍的方案
  dpr = 1;
 }
 scale = 1 / dpr;
 }
 //為html標(biāo)簽添加data-dpr屬性
 docEl.setAttribute('data-dpr', dpr);
 if (!metaEl) {
 metaEl = doc.createElement('meta');
 metaEl.setAttribute('name', 'viewport');
 // 動(dòng)態(tài)設(shè)置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);
 }
 }
 //根據(jù)dpr和物理像素設(shè)置rem
 function refreshRem(){
 //getBoundingClientRect().width相當(dāng)于物理像素
 var width = docEl.getBoundingClientRect().width;
 // width / dpr > 540等于獨(dú)立像素
 if (width / dpr > 540) {
  width = 540 * dpr;
 }
 var rem = width / 10; // 將屏幕寬度分成10份, 1份為1rem. rem轉(zhuǎn)化px計(jì)算公式=d*(width/10)
 docEl.style.fontSize = rem + 'px';
 flexible.rem = win.rem = rem;
 }
 // 監(jiān)聽(tīng)窗口變化,重新設(shè)置尺寸
 win.addEventListener('resize', function() {
 clearTimeout(tid);
 tid = setTimeout(refreshRem, 300);
 }, false);
 // 當(dāng)重新載入頁(yè)面時(shí),判斷是否是緩存,如果是緩存,執(zhí)行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、如何使用background-size

因?yàn)槭鞘褂昧藃em來(lái)做單位,我們?cè)趯懸苿?dòng)端的背景圖的時(shí)候,一般使用background-size來(lái)控制大小,那要怎么來(lái)?yè)Q算呢?

換算單位如下:

background-size=背景圖的大小/該設(shè)計(jì)圖的寬度*10

打個(gè)比方:我的背景圖是16*18,設(shè)計(jì)圖是按照640的寬度來(lái)設(shè)計(jì)的。那么我的background-size值為

background-size: 16/640*10rem 16/640*10rem   也就是 background-size:0.25rem 0.28125rem;

通過(guò)這樣控制之后,我們的背景圖也做到了適配的效果

2、雪碧圖的適配!?。?!

剛開(kāi)始做適配的時(shí)候,有一件事是比較頭疼的,那就是雪碧圖的適配,主要是background-size和background-position的配置比較煩。那么怎么進(jìn)行在使用fexible.js的時(shí)候適配雪碧圖呢,方法如下:

假如我有下面這張雪碧圖,設(shè)計(jì)圖給我的是按640的分辨率來(lái)做的。

這張雪碧圖的大小為200px*458px

移動(dòng)端界面的適配

假設(shè)現(xiàn)在我們要用的那個(gè)勛子的背景圖。分為以下幾步:

1、測(cè)量勛字這張背景圖的大小,大小為:75px*85px移動(dòng)端界面的適配

2、測(cè)量這個(gè)勛字在雪碧圖的位置,也就是設(shè)置background-position:.經(jīng)測(cè)量,他在雪碧圖的位置為 x:-123px,y:-7px

3、對(duì)著張雪碧圖進(jìn)行換算:看下面代碼:

知道了上面的尺寸,我們就行換算即可,將每個(gè)值除以640再乘以10   為什么這么算,可以看看源碼

要使用這樣雪碧圖:

<!-- 長(zhǎng)寬為: -->
width: 75/640*10=1.171875rem;
height: 85/640*10=1.328125rem;
<!-- background-size為 -->
<!-- 因?yàn)檎麖堁┍虉D的寬度為200px, -->
background-size: 200/640*10rem auto;
<!-- background-position為: -->
background-position: -123/640*10rem -7/640*10rem;  

html:

<i class="item1"></i>

css:

.item1{
 width: 75/640*10=1.171875rem;
 height: 85/640*10=1.328125rem;
 margin: 20px auto;
 background: url('../images/itemBg.png') no-repeat;
 // 因?yàn)檎麖堁┍虉D的寬度為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;
}

因?yàn)閾Q算比較麻煩,所以建議使用sass或者less來(lái)進(jìn)行計(jì)算。具體效果我放在了github上,可以看看:

https://github.com/xianyulaodi/flexibleDemo

適配的原理解析

先來(lái)了解一些概念

在進(jìn)行分析之前,首先得知道下面這些關(guān)鍵性基本概念(術(shù)語(yǔ))。

物理像素(physical pixel)

物理像素又被稱為設(shè)備像素,他是顯示設(shè)備中一個(gè)最微小的物理部件。一個(gè)物理像素是顯示器(手機(jī)屏幕)上最小的物理顯示單元,在操作系統(tǒng)的調(diào)度下,每一個(gè)設(shè)備像素都有自己的顏色值和亮度值。

其實(shí)可以類比為分辨率。打個(gè)比方,一張圖片有n多個(gè)很小很小個(gè)格子組成。

移動(dòng)端界面的適配

盜圖,哈哈

設(shè)備獨(dú)立像素(density-independent pixel)

設(shè)備獨(dú)立像素(也叫密度無(wú)關(guān)像素),可以認(rèn)為是計(jì)算機(jī)坐標(biāo)系統(tǒng)中得一個(gè)點(diǎn),這個(gè)點(diǎn)代表一個(gè)可以由程序使用的虛擬像素(比如: css像素),然后由相關(guān)系統(tǒng)轉(zhuǎn)換為物理像素。

所以說(shuō),物理像素和設(shè)備獨(dú)立像素之間存在著一定的對(duì)應(yīng)關(guān)系,這就是接下來(lái)要說(shuō)的設(shè)備像素比。

可以理解為css像素,比如寬度為20px等等。

設(shè)備像素比(device pixel ratio ),簡(jiǎn)稱dpr

設(shè)備像素比(devicePixelRatio簡(jiǎn)稱dpr)定義了物理像素和設(shè)備獨(dú)立像素的對(duì)應(yīng)關(guān)系,它的值可以按如下的公式的得到:

設(shè)備像素比 = 物理像素 / 設(shè)備獨(dú)立像素  

在javascript中,可以通過(guò)window.devicePixelRatio獲取當(dāng)前設(shè)備的dpr

css中的px可以看做是設(shè)備的獨(dú)立像素,所以通過(guò)devicePixelRatio,我們可以知道該設(shè)備上一個(gè)css像素代表多少個(gè)物理像素。

例如,在Retina屏的iphone上,devicePixelRatio的值為2,也就是說(shuō)1個(gè)css像素相當(dāng)于2個(gè)物理像素。

再舉個(gè)例子:iphone6中:

設(shè)備寬高為375×667,可以理解為設(shè)備獨(dú)立像素(或css像素)。

dpr為2,根據(jù)上面的計(jì)算公式,其物理像素就應(yīng)該×2,為750×1334。

是不是有點(diǎn)頭暈了,可以看看這篇文章消化一下:http://div.io/topic/1092

理解了上面的概念,就比較好理解它的實(shí)現(xiàn)原理了

理解它的原理有兩點(diǎn):

1、了解利用meta標(biāo)簽對(duì)viewport進(jìn)行控制

我們可以看看我們通常在head里面加的meta標(biāo)簽

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

該meta標(biāo)簽的作用是讓當(dāng)前viewport的寬度等于設(shè)備的寬度,同時(shí)不允許用戶手動(dòng)縮放。

content="width=device-width,讓viewport的寬度等于設(shè)備的寬度,如果不這樣的設(shè)定的話,那就會(huì)使用那個(gè)比屏幕寬的默認(rèn)viewport,會(huì)出現(xiàn)橫向滾動(dòng)條。

如果改變initial-scale的值,那么就可以讓頁(yè)面達(dá)到縮放

meta viewport 有6個(gè)屬性,可以了解一下

width 設(shè)置layout viewport  的寬度,為一個(gè)正整數(shù),或字符串"device-width"
initial-scale 設(shè)置頁(yè)面的初始縮放值,為一個(gè)數(shù)字,可以帶小數(shù)
minimum-scale 允許用戶的最小縮放值,為一個(gè)數(shù)字,可以帶小數(shù)
maximum-scale 允許用戶的最大縮放值,為一個(gè)數(shù)字,可以帶小數(shù)
height 設(shè)置layout viewport  的高度,這個(gè)屬性對(duì)我們并不重要,很少使用
user-scalable 是否允許用戶進(jìn)行縮放,值為"no"或"yes", no 代表不允許,yes代表允許

2、淘寶的移動(dòng)端頁(yè)面和flexible.js源碼解析:

第一個(gè)要點(diǎn):

淘寶觸屏版布局的前提就是viewport的scale根據(jù)devicePixelRatio(設(shè)備像素比) 動(dòng)態(tài)設(shè)置:

設(shè)備像素比的簡(jiǎn)單介紹:http://www.zhangxinxu.com/wordpress/2012/08/window-devicepixelratio/

來(lái)看一下flexible.js源碼:

移動(dòng)端界面的適配

移動(dòng)端界面的適配

根據(jù)不同的像素設(shè)備比,來(lái)對(duì)頁(yè)面進(jìn)行不同的縮放。頁(yè)面縮放的 scale=1/dpr ;

來(lái)看移動(dòng)端淘寶接下來(lái)的三張圖:https://m.taobao.com/#index

三星galasy S4 

data-dpr=1, 所以 initial-scale=1  (因?yàn)樵创a上 scale = 1 / dpr;)

移動(dòng)端界面的適配

iPhone5:

data-drp=2,所以initial-scale=0.5

移動(dòng)端界面的適配

iphone 6 Plus

移動(dòng)端界面的適配

第二個(gè)要點(diǎn):

動(dòng)態(tài)設(shè)置html的font-size,html元素的font-size的計(jì)算公式,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;

其實(shí)flexible的實(shí)質(zhì)就干了以下幾件事

1、動(dòng)態(tài)改寫meta標(biāo)簽

2、給元素添加data-dpr屬性,并且動(dòng)態(tài)改寫data-dpr的值。也就是動(dòng)態(tài)改寫dpr

3、給元素添加font-size屬性,并且動(dòng)態(tài)改寫font-size的值

以上就是移動(dòng)端適配的小小總結(jié),之前只是直接用,沒(méi)有好好的理解它的原理。發(fā)覺(jué)整理的時(shí)候,資料查下來(lái)也還是學(xué)到很多概念,學(xué)到挺多東西的。

以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持億速云!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI