設備像素比+圖片高清顯示+移動適配

 

1、設備像素比 dpr (devicePixelRatio)
 
首先進行概念的一些解釋:
 
一、物理像素(又稱硬件像素)(physical pixel)
一個物理像素是顯示器上最小的物理顯示單元,每個像素都有本身的顏色值和亮度。
同一個設備,它的物理像素是固定的,即一個設備的分辨率是固定的。
//計算公式:
//物理像素 = 邏輯像素 × 設備像素比
 
二、邏輯像素 dpi (又稱css像素、設備獨立像素)(density-independent pixel)
邏輯像素是指css樣式中使用的邏輯像素,也能夠說是設備的寬高。
iphone4以前的手機邏輯像素數和邏輯像素數是相等的,可是因爲視網膜設備(Retina屏)的出現,邏輯像素與物理像素之間有了不一樣的倍數對等關係。
//獲取方法
document.documentElement.clientWidth  //iphone6 => 320
document.documentElement.clientHeight  //iphone6 => 667
 
三、設備像素比 dpr (devicePixelRatio)
設備像素比 = 物理像素 / 邏輯像素
//js獲取方法
window.devicePixelRadio  //iphone6 =>2
注意點:
(1)在fireFox及ie中不支持window.devicePixelRatio
(2)在同一設備不一樣瀏覽器中,window.devicePixelRatio值可能不一樣,這是因爲不一樣的瀏覽器中css像素數不一樣
 
四、像素密度 ppi (pixels per inch)
每英寸中顯示的像素數,一般使用ppi來做爲像素密度的單位;計算公式: 對角線像素個數 / 屏幕尺寸         
對角線像素個數計算:(物理像素長² + 物理像素寬²)開根
 
 

 

 
不一樣手機物理像素、邏輯像素及像素比:

 

手機名稱
像素分辨率(px)
倍率
邏輯分辨率(pt)
物理尺寸(英寸)
屏幕密度(ppi)
DPI
i6 plus
1242*2208
@3x
414*736
5.5
401
154
I6
750*1334
@2x
375*667
4.7
330
163
I5s
640*1136
@2x
320*568
4
330
163
I5
640*1136
@2x
320*568
4
330
163
I4
640*960
@2x
320*480
3.5
330
163
I3GS
320*480
@1x
320*480
3.5
163
 
android
240*320
@0.75
320*420
120
   
android
320*480
@1x
320*480
160
   
android
480*800
@1.5x
360*500
240
   
android
640*960
@2x
320*480
320
   
android
540*960
@1.5x
360*640
360
   
android
720*1280
@2x
360*640
360
   
android
1080*1920
@3x
360*640
360
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
綜合以上幾個概念,以Iphone6舉例說明:設備寬高(即邏輯像素)爲:375×667 ,dpr爲2,物理像素爲 750×1334
//css樣式
width:1px;
height:1px;

 

相同尺寸下,普通屏幕 VS Retina 屏,css像素所呈現的物理尺寸(大小)是一致的,不一樣的是一個css像素所對應的物理像素的個數不一致:
普通屏幕:css像素:物理像素 = 1:1
retina屏: css像素:物理像素 = 1:4
即4個物理像素顯示一個css像素;
 
2、圖片高清顯示
首先了解一下圖片的顯示規則:
位圖像素:一個位圖像素是柵格圖像最小的數據單元。每一個位圖像素都包含自身的顯示信息,如色值,透明度等
理論上,當位圖像素對應物理像素時,圖片才能清晰展現。
例如:img標籤,css像素爲200*300,普通屏幕下對應物理像素爲200*300,retina屏幕對應物理像素爲400*600:
    (1)當在retina屏中,使用200*300@1x圖片時,因爲每一個單位的位圖像素不可分割,只能就近取色,從而致使retina屏圖片模糊;使用兩倍圖片@2x,如200*300的img標籤,使用400*600的圖片,這樣retina屏幕下,物理像素:位圖像素 = 1:1,圖片清晰
    (2)若是在普通屏下使用@2x圖片,一個物理像素對應4個位圖像素,它的取色須要必定的算法,顯示結果就只有原圖像素總數的4分之一(這個過程叫downsampling),圖片雖然不會模糊,可是會少一些銳利度或者色差;一樣會形成資源浪費

 

最好的解決方案:不一樣的dpr下,使用不一樣尺寸的圖片。
(1)能夠經過媒體查詢或者js進行控制,拼接不一樣的url
(2)img標籤,設置srcset屬性
//srcrest 以最合適的src去匹配不一樣屏幕(高分屏低分屏如Retina;大屏小屏)
//  2x、3x 表示目標屏幕的像素密度
< img src ="source.jpg" srcset ="source_2x.jpg 2x, source_3x.jpg 3x" >
//400w、600w表示目標瀏覽器的寬度的限度,如瀏覽器寬度550w時,匹配600w的src
< img src ="source.jpg" width ="100%"  srcset ="source_400.jpg 400w, source_600.jpg 600w, source_1280.jpg 1280w" >
 
2、移動端適配之rem
適配前提:
<meta name= "viewport" content= "initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width" >
 
設配原理:使用rem單位進行移動端佈局適配,原理是針對不一樣手機屏幕尺寸和dpr動態的改變根節點html的font-size大小
 
一、js方法實現
 
(1)引入flexible.js,改變根元素font-size
 
; ( 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 ;
}
 
docEl. setAttribute ( 'data-dpr' , dpr) ;
window.dpr = dpr ;
 
if (!metaEl) {
metaEl = doc. createElement ( 'meta' ) ;
metaEl. setAttribute ( 'name' , 'viewport' ) ;
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) ;
}
}
 
function refreshRem (){
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 ;
}
 
win. addEventListener ( 'resize' , function () {
clearTimeout (tid) ;
tid = setTimeout ( refreshRem , 300 ) ;
} , false ) ;
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' ] = {})) ;
 
 
(2)css使用rem爲單位
css代碼中如何還原視覺稿尺寸:視覺稿通常均爲二倍視覺稿,例如:以iphone6(設備尺寸375*667)作設計標準,高清設計稿爲750 * 1334,html的font-size會被設置爲 75px
方法一:利用sass/less @mixin計算
@mixin px2rem($attr,$value){
    $attr:($value / 75) * 1rem
}
 
p{  //設計稿 300* 300 的元素
    @include px2rem(width,300);
     @include px2rem(height,300) ;
}
 
方法二:打包工具 postcss-px2rem 
css代碼中按照設計稿尺寸編寫,css文件利用打包工具,打包爲rem單位
//gulpfile.babel.js
//具體使用方法請參考官網
px2rem({
remUnit : 75  //設計稿尺寸/10
}) ,
注意:
使用rem爲單位,1px邊框轉化爲rem後,在andriod等版本手機,因爲實際計算邊框寬度不足1px,因此,邊框不顯示;
解決方法:(1)增長邊框寬度,經實測2.5px邊框,ios和andriod手機效果兼容性更好
                 (2)在sass文件中,在不須要轉化rem的地方,添加註釋 /*no*/
. testDiv {
     border : 1 px solid red ; /*no*/
     height : 100 px ;
     line-height : 100 px ;
     font-size : 75 px ;
}
 
二、css媒體查詢實現
html{
    font-size:32px;
}
@media ( min-device-width : 320 px ){
     html {
          font-size : 32 px ;
     }
}
@media ( min-device-width : 375 px ){
     html {
          font-size : 37.5 px ;
     }
}
@media ( min-device-width : 414 px ){
     html {
          font-size : 41.4 px ;
     }
}
 
缺點:根據設備寬度媒體查詢設置根元素font-size,不夠準確,只能設置某一範圍,賦予相同字號
 
 
 
 
 
 
 版權聲明:本文爲博主原創文章,未經博主容許不得轉載。 http://www.cnblogs.com/zuozuo-blog/
 
 
參考文章:https://www.cnblogs.com/jingwhale/p/5741567.html
                https://blog.csdn.net/a0405221/article/details/78913714
相關文章
相關標籤/搜索