進入移動Web世界
- 2019 年 10 月 4 日
- 筆記
# WebApp
一、 移動端web基礎
1. Pixel
- px: CSS pixels 邏輯像素,瀏覽器使用的抽象單位;
- dt,pt: 設備無關像素;
- dpr: 設備像素縮放比;
- 公式:1px = (dpr)2 * dp
默認縮放比例:
|
ldpi |
mdpi |
hdpi |
xhdpi |
---|---|---|---|---|
ppi |
120 |
160 |
240 |
320 |
默認縮放比例 |
0.75 |
1.0 |
1.5 |
2.0 |
2. Viewport
手機瀏覽器默認做了兩件事
- 頁面渲染在了一個默認的viewport;
- 縮放;
那麼問題來了,為什麼會有一個默認的viewport呢?我們知道,pc端頁面,在移動端查看的時候,由於像素不匹配,但是為了能夠給用戶展現一個比較完整的頁面,因此會虛擬出一個viewport出來,在此viewprot上渲染頁面。也就是說,最終目的,是為了排版正確。但是由於一般默認情況下,給出的viewport像素寬對頁面來說是不友好、不規範的,因此我們還需要解決一個規範問題。解決方案:在head中加一個meta標籤格式如下:<metaname="viewport"content="name=value, name=value">
3. meta標籤
<meta name="viewport" content="name=value, name=value"> // name = value 對應關係 width: device-width; initial: xx; // 設置初始縮放 minimum-scale: xx; // 最小縮放 maxim-scale: xx; // 最大縮放 user-scalable: no; // 用戶不可縮放
二、 高效的移動web布局
1. flexbox彈性布局
- flex布局混合排版
/* 混合使用flex佔比 */ .nav{ display: -webkit-flex; } .son1{ flex: 1; } .son2{ flex: 3; } .son3{ width: 100px; }
- flex水平垂直居中
.parent{ justify-content: center; align-items: center; display: -webkit-flex; }
2. flex兼容性
- iOS可以使用最新的flex布局;
- Android4.4以下,只能兼容舊版flexbox布局;
- Android4.4及以上,可以使用最新的flex布局;
表現如下:
新felx布局 |
舊flexbox布局 |
---|---|
display: -webkit-flex; |
display: -webkit-flex-box; |
-weblit-flex: 1; |
-weblit-flex-box: 1; |
justify-content: center; |
box-pack: center; |
align-items: center; |
box-align: cneter |
3. 響應式設計
顧名思義,一套頁面,在所有端(pc、超大屏、ipad、手機等)完美運行。隨頁面寬高變化而改變頁面樣式,從而適配不同設備。
媒體查詢 @media
@media screen and (max-width: 1024px) { body{ background: #eee; } } @media screen and (max-width: 980px) { body{ background: green; } } @media screen and (max-width: 720px) { body{ background: yellow; } } @media screen and (max-width: 640px) { body{ background: skyblue; } } @media screen and (max-width: 320px) { body{ background: pink; } } @media screen and (min-width: 1025px) { body{ background: darkseagreen; } }
媒體類型
- screen:螢幕
- print:印表機
- handhead:手持設備
- all:通用
常用參數說明
- width: 視口寬
- height: 視口高
- device-width: 設備寬
- device-height: 設備高
- orientation: 檢查設備橫屏豎屏處向(landscape橫,portrait豎)
設計點
- 百分比布局:使切換css不同媒體樣式時更加平滑
- 彈性圖片:圖片根據盒子百分比,改變盒子寬高即可
- 重新布局,顯示和隱藏:
- 同比例縮減元素尺寸
- 調整頁面結構布局
- 隱藏冗餘的元素
優劣比較
- 優點:減少重複開發,一套程式碼多端兼容
- 劣勢:在極端情況下影響頁面性能,含有較多的冗餘程式碼
4. 移動web特別樣式處理
a. 高清圖片處理
width: (wvalue / dpr)px height: (hvalue / dpr)px
b. 1像素邊框問題
問題: Retina螢幕下,1像素問題原因: 1px使用2dp渲染解決:
/* 錯誤案例 */ div{ border-top: 0.5px; } /* 正確案例 */ div:before{ border-top: 1px; -webkit-transform: scaleY(0.5); position: absolute; top: -1px; left: 0; content: ''; height: 1px; }
c. 相對單位
- em: 根據父節點的font-size為相對單位
- rem: 根據html的font-size為相對單位 (建議使用)
那麼,rem的基值設置為多少比較合適呢?回歸到開發中來,我們有一個公式:rem=screen.width/x
例:320的螢幕,可以設置為font-size=32px,而375的螢幕,設置為37.5px。我們的目的是為了方便計算。
d. 文本溢出
/* 單行文本溢出*/ .line{ overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } /* 多行文本溢出 */ .lines{ display: -webkit-box !important; overflow: hidden; text-overflow: ellipsis; word-break: break-all; -webkit-box-orient: vertical; -webkit-line-clamp: 2; // 行數 }
三、 終端交互優化
1. 300ms延遲問題
在移動端,由於有多重手勢操作替代了滑鼠操作,因此,為了判斷出是點擊、雙擊、觸摸移動或者別的手勢,iOS系統判斷中加了一個300毫秒的延遲:在第一次出發事件300毫秒內再次出發,例如點擊,就會被判斷為雙擊。那麼為了統一規範,後來在Android系統中也加入了此判定。這就是著名的移動端300ms延遲問題。那麼如何解決這個問題呢?tap事件處理。什麼是tap事件?簡而言之,就是通過touch,監聽touchstart和tarchend,如果兩者間隔較短,例如100ms甚至更短,且起始位置的偏移量極小,控制在幾個像素之內,那麼就判定為點擊事件。如此操作,可以繞過系統300ms的規範,從而在用戶體驗上做的更優。但我們只有,一般有利就有弊。我們解決掉300ms延遲問題,從而又產生了一個新的問題,就是穿透問題。例如在按鈕上有一個蒙層,我們點擊蒙層,關閉其蒙層。但是如果在蒙層下面同樣有點擊事件,那麼我們在點擊蒙層關閉後,也會觸發到下面的事件。那麼這種問題的一般解決方案便是關閉蒙層的時候,添加一個300ms的延時,經過300ms延時關閉後,點擊不再具有穿透性,巧妙的解決的該穿透問題。但是問題又來了,300ms延時其實對用戶體驗來講並不那麼友好。因此還是推薦第一種解決方案,不會出現拆東牆補西牆或者說捉襟見肘的問題。當然,如果使用框架庫的話,大部分強大的庫默認都解決了這個問題,不用開發者再為此操心。
2. touch相關
觸摸是移動設備交互的核心事件
a. 觸摸事件
事件 |
觸發情況 |
備註 |
---|---|---|
touchstart |
手指觸控螢幕幕觸發 |
已有手指放在螢幕上則不觸發 |
touchmove |
手指在螢幕上滑動 |
連續觸發 |
touchend |
手指離開螢幕時觸發 |
/ |
touchcancel |
系統取消touch時觸發 |
不常用 |
b. 事件屬性
- touches:跟蹤觸摸操作的touch對象數組
- targetTouches:特定事件目標的touch對象數組
- changeTouches:上次觸摸改變的touch對象數組
c. 每個touch對象包含屬性
- clientX:觸摸目標在視口中的橫坐標
- clientY:觸摸目標在視口中的縱坐標
- identifier:標識觸摸的唯一id
- pageX:觸摸目標在頁面中的橫坐標(含滾動)
- pageY:觸摸目標在頁面中的縱坐標(含滾動)
- screenX:觸摸目標在螢幕中的橫坐標
- screenY:觸摸目標在螢幕中的縱坐標
- target:觸摸的DOM節點的目標
d. 相關bug
在Android中,某些版本只會觸發一次touchstart和一次touchmove,不會觸發touchend。解決方案則是在事件中(touchmove)添加阻止默認事件:event.preventDefault()
。但與此同時,要注意隨之產生的一個問題,就是組織默認事件後,頁面也會隨之禁止滾動,因此看情況使用。