摘要:不要再問我的問題系列一不要再問我的指向問題了二不要再問我跨域的問題了移動端適配的問題,一般來說我們都不會去深究,因為這種東西都是配置一次就再也不用管的了,接到設計圖就按照祖傳套路擼就完事了。
“不要再問我XX的問題”系列:
一、不要再問我this的指向問題了
二、不要再問我跨域的問題了
移動端適配的問題,一般來說我們都不會去深究,因為這種東西都是配置一次就再也不用管的了,接到設計圖就按照祖傳套路擼就完事了。按部就班的必定只能成為活動頁寫手,研究透徹以后,才能成為一名專業的活動頁寫手嘛。
糾纏不清的關系文章開始,我們需要來捋清楚像素、視口以及縮放之間種種藕斷絲連的關系,來抽絲剝繭一波。
像素像素我們寫得多了,不就是px嘛,為什么要拿出來說呢?因為像素還不僅僅就是px。
設備像素
設備像素也可以叫物理像素,由設備的屏幕決定,其實就是屏幕中控制顯示的最小單位。
設備獨立像素
設備獨立像素是一種可以被程序所控制的虛擬像素,在Web開發中對應CSS像素。
DPR
設備像素與設備獨立像素之間的關系就是,DPR(設備像素比),設備像素比 = 設備像素 / 設備獨立像素。這條公式成立的前提是,縮放比為1,原因下面講到縮放的時候就會知道。根據這種關系,如果設備像素大于設備獨立像素(DPR大于1的設備,我們常說的高清屏或者Retina屏),就會出現一個設備獨立像素對應多個設備像素的情況:
遙想從前智能手機剛出的時候,很少網站去特意適配移動端,然而用戶是可以直接從手機去訪問PC端網站的,所以怎樣顯示好一個網站,無論這個網站是一個PC網站還是移動端網站,就是亟需解決的問題。所以移動端三個視口布局視口、視覺視口、理想視口橫空出世,成為各種移動適配方案的基礎。
布局視口
布局視口是在html元素之上的容器,我們的頁面就“裝”在布局視口中。
想想我們常寫的width:100%,這個100%是基于什么計算出來的呢?去翻資料會看到:如果某些屬性被賦予一個百分值的話,它的計算值是由這個元素的包含塊計算而來的。那html元素的包含塊是什么呢?沒錯,就是我們的布局視口,它是所有CSS百分比推算的根源,如果說CSS是一支畫筆,那么布局視口就是那張畫布吧。這張畫布有一個默認尺寸(如果沒有手動去設置meta viewport),一般在768px ~ 1024px間,可以通過document.documentElement.clientWidth獲取。這樣一來,網頁的布局就不再受限于設備的尺寸,即使是小屏幕的移動端設備中也能容得下PC網站。
視覺視口
視覺視口是指用戶通過設備屏幕看到的區域,可以通過縮放來改變視覺視口的大小,并通過window.innerWidth獲取。
這里有必要講一下縮放,縮放改變的是CSS像素的大小,放大時CSS像素增大,則一個CSS像素可以跨越更多的設備像素,視覺視口會變小。什么?放大反而視覺視口變小?沒錯,這是因為視覺視口也是通過CSS像素度量,而放大就是使CSS像素放大,假設屏幕上本來需要200個CSS像素才能占滿屏幕,由于放大,現在只需要100個CSS像素就能占滿,所以視覺視口的寬就變成100px。
雖然縮放改變了CSS像素的大小,但移動端的縮放是不會改變布局視口的,所以縮放并不會影響布局,不過在PC端是會影響布局的。最直觀的感受是,我們平時在移動端雙指縮放網頁,整個網頁的布局是沒有變化的,可以通過拖動來看到不同區域的東西,但是在PC端進行縮放,比如閱讀時想文字大一些而對網頁進行放大操作,這時字是放大了,但整個頁面的布局會有所改變。那么既然與布局視口無關那還跟誰有關系呢?答案就是下面準備要講的理想視口,它們之間的計算方式是:縮放系數 = 理想視口寬度 / 視覺視口寬度
理想視口
理想視口是指網站在移動設備中的理想大小,這個大小就是設備的屏幕大小。
為什么需要理想視口呢?首先,先來看看現在的情況是怎么的不理想。我們在瀏覽一個沒經過移動適配的網站時,由于布局視口在768px ~ 1024px之間,整個網站就“畫”在一個這么大的“畫布”上,但由于手機屏幕比“畫布”小,所以需要經過縮小才能塞進手機屏幕,結果我們瀏覽網站的時候雖然看得見全貌,但里面的東西都變得很小,需要放大一下才能看得清,就是這么不理想。如果不需要放大就可以看得清那就很理想了嘛。回想一下上面不理想的解決方案,就是將一個大畫布經過縮小裝進小屏幕里,假設現在畫布跟屏幕一樣大,就在這個畫布上作畫,豈不是很合適?
所以總結起來,理想視口說白了就是理想的布局視口,通過來設置。
元素可提供有關頁面的元信息,不會顯示在頁面上,可以用來告訴瀏覽器怎樣解析頁面。可以設置的東西很多,但這里只講vieport,它是所有移動適配方案的基礎。
首先meta viewport的設置格式是,其中name的值可設為:
width:將布局視口設置為固定的值,比如375px或者device-width(設備寬度)
initial-scale:設置頁面的初始縮放
minimum-scale:設置最小的縮小程度
maximum-scale:設置最大的放大程度
user-scalable:設置為no時禁用縮放
雖然只有五個值,但仍有一些值得注意的點:
設置initial-scale的影響根據公式縮放系數 = 理想視口寬度 / 視覺視口寬度 ,如果設置了initial-scale比如為0.5,那么以iPhone6為例,iPhone6的設備寬度是375px,即理想視口寬度也為375px,所以視覺視口寬度 = 375px(理想視口寬度)/ 0.5(縮放系數)。很明顯設置了initial-scale就相當于初始化了視覺視口,而且會將布局視口初始化為這個視覺視口的值。
width和initial-scale共存上面說到設置了initial-scale相當于初始化了視覺視口和布局視口,但width用于指定布局視口的大小,那么一起設置的話聽誰的呢?
還是以iPhone6為例,它的尺寸是667(h) * 375(w),如果設置,執行一下console.log(`布局視口: ${document.documentElement.clientWidth}; 視覺視口: ${window.innerWidth}`)會得到“布局視口: 400; 視覺視口: 400”。
這時候旋轉一下設備,這時尺寸變成了667(w) * 375(h),再執行一下console.log(`布局視口: ${document.documentElement.clientWidth}; 視覺視口: ${window.innerWidth}`)會得到“布局視口: 667; 視覺視口: 667”。
結論是:width與initial-scale都會初始化布局視口,但瀏覽器會取其最大值。
這時候再看回,明明width=device-width和initial-scale=1都是去初始化布局視口成理想的布局視口,只寫其中一個不就完了嘛,為什么要兩個都一起寫呢?因為有的瀏覽器只設置其中一個,不能保證理想視口的尺寸能隨著屏幕的旋轉而正確改變,所以兩個一起寫只是為了解決兼容性問題。
舒服地還原移動端設計圖上面說了很多理論知識,其實就是為了能有一套方案舒服地還原移動端設計圖,做出一個專為移動端訪問的頁面。
經典的問題圖片
這里的圖片問題是指高清/Retina屏下圖片會顯示得比較模糊,這是因為我們平時使用的圖片大多數是png、jpg這樣格式的圖片,它們稱作是位圖圖像(bitmap),是由一個個像素點構成,縮放會失真。上面講像素的時候說過,這種高清/Retina屏DPR大于一,則一像素橫跨了多個設備像素,而位圖圖像需要一個像素點對應一個設備像素才清晰。所以假設一張100 x 100的圖片放在普通屏上看是清晰的,放到高清/Retina屏上就會顯得比較模糊,那是因為本來100 x 100的圖片在普通屏上圖片像素與設備像素一一對應,而到了高清/Retina屏上一個圖片像素卻要對應多個設備像素,這樣一來看起來圖片就比較模糊。
如圖所示,如果一個圖片像素要對應多個設備像素的話,那這些設備像素只能顯示成跟這個圖片像素差不多的顏色,導致看起來會模糊。
既然知道了問題產生的原因,那解決方法也很簡單,位圖圖像需要一個像素點對應一個設備像素才清晰嘛,那就本來是100 x 100的圖片在DPR為1的屏幕上顯示清晰,在DPR為2的屏幕上顯示模糊,那就在DPR為2的屏幕上放200 x 200的圖好了,這樣就一一對應了。
1px邊框
“你看看設計圖這根線是很細的,為什么你實現出來那么粗,看起來很劣質的感覺。”
沒道理呀,設計圖量的是1px,css寫的也是1px,怎么會粗了呢?一般設計師出圖的時候,都會按照一個尺寸作為標準來出圖,比如按照iPhone6的尺寸出圖,就是一張750px寬的設計圖,這個750px其實就是iPhone6的設備像素,在測量設計圖時量到的1px其實是1設備像素,而當我們設置時,布局視口等于理想視口等于375px,并且由于iPhone6的DPR為2,寫css時的1px對應的是2設備像素,所以看起來會粗一點。
那么只要寫0.5px就是對應1設備像素了嘛。是的,道理是這么說,但是很多瀏覽器并不支持0.5px的寫法,導致顯示不出來,但不要緊,網上很多方法解決這個問題的方法就不細說了,這里只是講清楚1px邊框問題產生的原因。
因為PC端屏幕一般都會比設計圖尺寸要大,所以只需要居中固定一個內容區用于顯示設計圖的內容,其余多出的地方留白即可。而移動端屏幕有大有小,設計圖一般會以一款機型為標準來出圖,比如說iPhone6的尺寸,如果不經處理直接量設計圖就開干會出現什么問題呢?
(從左到右為iPhone4、iPhone6、iPhone plus)
可以看到以iPhone6為標準出的設計圖測量出來350px x 350px的元素在iPhone6上寫width: 350px;height: 350px;是剛剛好的,左右的間隙各有10px,但小一點的屏幕iPhone4橫向滾動條都出來了,而plus左右間隙明顯比10px大很多,這樣一來不同尺寸的屏幕出來的效果跟設計圖的效果就會有不同程度的出入,這并不是我們想要的,我們想要的是不同尺寸的屏幕顯示的效果與設計圖比例是一致的。
既然想要的是不同屏幕尺寸顯示的比例與設計圖一致,那么顯然適配方案就是等比縮放。
(以下代碼都是為了講述原理,沒有過多的細節考慮與測試,不能用于生產環境)
viewport方案
說到縮放,首先想到的當然是initial-scale。回想一下initial-scale的作用:設置了initial-scale就相當于初始化了視覺視口,而且會將布局視口初始化為這個視覺視口的值。那么我們是不是可以以設計圖為基準等比縮放布局視口從而適配呢?
這種方式進行適配優點是簡單粗暴,缺點是太簡單粗暴了,因為viewport的設置是影響全局的,這樣一來雖然可以直接將設計圖量得的尺寸寫到css上,但如果有一些需要地方不需要等比縮放而需要設置固定尺寸,比如要求在不同尺寸屏幕上顯示固定大小的文字,或者你引進了一個庫,里面的有樣式你也不知道人家是按照怎樣的適配方案進行適配的,那么到了你的項目里由于全局的viewport縮放,可能會影響到這個庫的顯示效果。
rem方案
不同于px是固定尺寸單位,rem是相對單位,相對于html標簽字體大小的單位。比如html標簽的font-size為100px,那么1rem就等于100px。借助rem這個相對單位我們同樣可以達到等比縮放的效果。
這個方案不需要對viewport進行縮放,所以首先按照慣例我們讓布局視口等于理想視口:
還是以iPhone6的設備像素為標準的設計圖,寬是750px,假設以設計圖為標準的html標簽的font-size為100px,所以1rem = 100px,那么這個設計圖總寬就有7.5rem
以總寬是7.5rem的設計圖為標準,則不同屏幕尺寸的總寬應該也是7.5rem,由于上面設置了布局視口等于理想視口,所以以iPhone6為例,iPhone6的布局視口等于理想視口,則它的布局視口為375px(也就是總寬7.5rem),現在只需要解決在布局視口為375px的情況下,html的font-size需要設置多少。很簡單,html font-size * 7.5 = 375,那么font-size為50px。
拓展到其他屏幕document.documentElement.style.fontSize = `${document.documentElement.clientWidth / 7.5}px`
現在我們只需要測量設計圖,比如設計圖有一個300px的元素,那我們寫css的時候就寫成3rem(由于以1rem = 100px為基準,所以這里300px / 100即可)
使用這個方案,我們只對需要等比縮放的元素使用rem,而要求固定尺寸的地方使用px即可,這樣一來相對于viewport方案來說就比較靈活,可以按需使用而不是一刀切。不過這種方案寫css的時候可能會沒那么直觀,成本可能會高一點點,但是借助構建工具或者less/sass可以解決,畢竟現在應該很少項目不使用這些工具的了吧。
加強版rem方案
這里所說的加強版rem方案其實就是手淘的Flexible方案(也類似移動端高清、多屏適配方案),究竟加強了什么呢?那就是,通過設置viewport進而全局解決1px邊框問題。
既然要通過設置viewport來解決1px邊框問題,那設置這個viewport的方式肯定內有乾坤:
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) { 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; }
得出的scale用于設置viewport的縮放document.write(``),這樣一來,對于Retina屏將viewport縮放為1 / dpr最終產生的效果是,1px css像素嚴格等于1px 設備像素,由此解決了1px邊框問題。那為什么只對iPhone進行縮放呢?請看大漠老師的文章再談Retina下1px的解決方案。
其他與rem相關的配置與上面的rem方案類似,這里就不再展開說了。
這個加強版rem方案最大的優勢是解決了1px邊框問題,但由此也進行了viewport的縮放,仍然會面臨著上面說的viewport方案涉及到的一些影響,為此該方案會通過給html設置data-dpr
document.documentElement.setAttribute("data-dpr", dpr)
從而寫css的時候可以針對不同的dpr固定設置尺寸:
.test { width: 1rem; height: 2rem; font-size: 12px; } [data-dpr="2"] .test { font-size: 13px; } [data-dpr="3"] .test { font-size: 14px; }
vw方案
vw也是一個相對單位,它相對的是布局視口,1vw就是1%的布局視口寬度。其實rem方案就是在模擬vw,來看看使用vw怎么做。
還是熟悉的iPhone6標準設計圖,寬750px。那么1vw = 1%視口寬度的話,按設計圖來說就是100vw = 750px,則1vw = 7.5px。
設計圖量得一個元素是100px,css需要寫成 Xvw * 7.5 = 100,所以X就等于13.3vw。
計算的話還是交給構建工具即可,詳細請看再聊移動端頁面的適配
rem方案有的優勢vw也有,而且也不會像rem那么繞,但就是兼容性不夠rem好,長遠來看vw最后會接棒rem作為移動適配的主力,因為它生來就干這個事情呢。
終于結束了沒有銀彈。
全局viewport縮放方案很粗暴?但對于要求不高也不需要兼顧固定尺寸的頁面,上來就全局縮放,拿起設計稿就可以寫代碼了。要求高又想靈活,還會怕構建的那一點點麻煩嗎?rem方案走起。兼容性不需要考慮,那vw方案直白又優雅不試試看嗎?方案沒有優劣之分只有合適與否。
最后,如果有說得不對的地方,還望指正。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/117183.html
摘要:不要再問我的問題系列一不要再問我的指向問題了二不要再問我跨域的問題了移動端適配的問題,一般來說我們都不會去深究,因為這種東西都是配置一次就再也不用管的了,接到設計圖就按照祖傳套路擼就完事了。 不要再問我XX的問題系列:一、不要再問我this的指向問題了二、不要再問我跨域的問題了 移動端適配的問題,一般來說我們都不會去深究,因為這種東西都是配置一次就再也不用管的了,接到設計圖就按照祖傳...
摘要:不要再問我的問題系列一不要再問我的指向問題了二不要再問我跨域的問題了移動端適配的問題,一般來說我們都不會去深究,因為這種東西都是配置一次就再也不用管的了,接到設計圖就按照祖傳套路擼就完事了。 不要再問我XX的問題系列:一、不要再問我this的指向問題了二、不要再問我跨域的問題了 移動端適配的問題,一般來說我們都不會去深究,因為這種東西都是配置一次就再也不用管的了,接到設計圖就按照祖傳...
摘要:所以構造函數里的指的就是將要被出來的新對象。希望看完這篇文章之后,再有人問指向的問題,你可以嘴角微微上揚,冷笑一聲不要再問我的指向問題了。 this的指向已經是一個老生常談的問題,每逢面試都要去復習復習,近來鞏固js的基礎,決心徹底掌握這個知識點,一勞永逸。說明一下,為了不影響大家的思考過程,下面的代碼都不會去注釋答案,想知道答案,只需要去控制臺執行一下。 四類場景逐一擊破 首先,分析...
摘要:不過大多數講解還停留在對功能使用的層面,其底層的很多原理,很多人可能并不知曉。每個線程池里的線程就僅僅用于請求那個服務。 歡迎關注微信公眾號:石杉的架構筆記(id:shishan100) 每日更新!精品技術文章準時送上! 目錄 一、業務場景介紹 二、Spring Cloud核心組件:Eureka 三、Spring Cloud核心組件:Feign 四、Spring Cloud核心組件:R...
摘要:不過大多數講解還停留在對功能使用的層面,其底層的很多原理,很多人可能并不知曉。每個線程池里的線程就僅僅用于請求那個服務。 歡迎關注微信公眾號:石杉的架構筆記(id:shishan100) 每日更新!精品技術文章準時送上! 目錄 一、業務場景介紹 二、Spring Cloud核心組件:Eureka 三、Spring Cloud核心組件:Feign 四、Spring Cloud核心組件:R...
閱讀 3642·2021-11-15 11:37
閱讀 2310·2021-09-24 10:39
閱讀 2423·2021-07-25 21:37
閱讀 1404·2019-08-30 15:56
閱讀 2575·2019-08-30 15:55
閱讀 943·2019-08-30 15:54
閱讀 2117·2019-08-30 14:21
閱讀 847·2019-08-30 11:24