APP開發目前有三種趨勢,一種是原生APP,一種是網頁APP,還有一種是H5APP。css
移動web開發:html
因爲是基於webview,因此能夠跨平臺,不管是android仍是ios,都能很好的呈現。webview能夠理解爲是咱們的移動web頁面和咱們手機原生之間的一箇中間橋樑。
複製代碼
也被稱爲設備像素 (Device independent pixels),即設備在出廠的時候就已經固定了像素。vue
咱們來看一下 iPhone6 (左圖) 與 iPhone6 plus (右圖) 的官方顯示屏的規格說明:react
iPhone6 是 1334px x 750px 的像素分辨率,意思是當手機豎放的時候,橫向有 750 個物理像素,縱向有 1334 個物理像素。android
在 CSS 中也被稱爲 CSS 像素 (CSS pixels),是爲 Web 開發者創造的,在 CSS 和 JavaScript 中使用的一個抽象的層,每個 CSS 聲明和幾乎全部的 Javascript 屬性都使用 CSS 像素。ios
例如咱們平時使用 Chrome 的設備調試工具的時候,iPhone6 是高 667px,寬是 375px,與蘋果官方的 1334px x 750px,長寬分別少了 2 倍,那麼面積就少了 4 倍。這就是常常說的 Retina 屏幕用四個(物理)像素表示一個(邏輯)像素。css3
咱們看的屏幕都是由一個一個的像素點組成的,以前咱們一直說的分辨率都是指實際像素尺寸,好比: 1920 * 1080就是 1920個像素點 * 1080個像素點。每一個點發出不一樣的光就構成了咱們所看的畫面。git
而到了咱們的移動端就不同了,由於咱們的手機自己就那麼寬,要放下一個較寬的頁面,顯然,這種上訴的像素排放就不合適了。github
因此咱們要引入一個概念了: 像素密度(PPI)
。web
PPI: 準確的說是每英寸的長度上排列的像素點數量。1英寸是一個固定長度,等於2.54釐米.意思是一英寸中有多少個物理像素。
咱們再來看上面的圖,一樣的物理大小,PPI越高,所佔據的像素點就越多,越高PPI的屏幕,顯示一個像素點的面積就越小,一張由4x4個像素點組成的圖顯示在PPI爲64的屏幕上,那麼換到256PPI的屏幕上顯示則會縮小爲原來大小的一半。
反過來,若是要在PPI爲256的屏幕上顯示效果與PPI爲64的屏幕同樣,那麼得要把圖片放大2倍。
所以配有高清屏幕的手機,廠商爲了其設備的可用性,即圖標和文字能夠被正確識別和準確點擊,就必須保證各種素材在其設備上的顯示與標清設備同樣,而這個解決方法就是把全部尺寸都放大若干倍。這個放大比例就叫做設備像素比。
所以高清設備上應該配有高清圖片顯示,否則圖片在高清設備上放大後沒有足夠的像素顯示其細節,那麼這張圖片就會變得看起來很模糊。
在DPR爲1(一般咱們的PC),1px等於1個物理像素。DPR爲2,1px等於2個物理像素。
總結:
1. 咱們在開發中通常儘量使用iphone 6s來看成測試頁面
2. 設計師給咱們的圖紙通常都是使用該機型的像素尺寸來做圖的
3. 咱們的話通常仍是使用物理尺寸(設備尺寸)來直觀感覺和設計頁面
4. 因爲iphone6s的縮放比例是2倍,所以咱們使用的css像素就能夠是設計圖紙像素的一半。
複製代碼
在移動端打開一個頁面,若是瀏覽器先會以正常的比例來渲染頁面,而後再自動地設置一個比例來縮放頁面,目的是爲了讓內容更好地展現出來,即頁面內容恰好鋪滿整個手機屏幕,固然若是頁面沒有禁止掉用戶縮放的話,你也能夠用兩個手指把頁面縮放回原始的比例。這整個過程就是經過視口(viewport)來實現的,原始頁面渲染好後經過視口縮放使得與系統寬度同樣,從而能夠完整地展現頁面。
移動端有三種視口:
佈局視口: layout viewport
可視視口: visual viewport
理想視口: ideal viewport
複製代碼
由於移動端的屏幕尺寸都比較小,咱們的頁面根本放不下,這就有了佈局視口的概念了,佈局視口是虛擬的,通常都比較大,用戶能夠經過移動頁面,縮放來經過可視視口查看頁面的所有內容。
這時候雖然咱們的頁面被縮放,顯示在了可視視口內了,可是咱們的頁面過小,容易影響用戶的操做。
這時候就提出了理想視口,最初是由蘋果公司提出的。理念:讓咱們的佈局視窗,等於咱們的理想視窗。而後把咱們頁面的元素正好放入到咱們的頁面中,元素的大小符合大衆的閱讀。
實現理想視窗,一般是:
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
複製代碼
具體可看個人另外一篇文章。 響應式設計之 —— 媒體查詢
首先咱們須要設置視窗
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
複製代碼
而後設置html根元素的字體大小。
html{font-size:13.33333333vw}
複製代碼
寫的width:1rem,heigth:1rem
的div
就是50px* 50px
(iphone6爲2倍屏,即對應750px設計稿上的100px*100px) 怎麼搞定的,1句代碼就能實現,太神奇。
原理:
vw爲屏幕寬度的1/100。咱們的設計稿是750px的。那麼100/750 = 0.1333333,那麼1px就是0.1333333vw。100px就是13.333333vw了。這樣咱們就能愉快的寫rem了。當咱們html設置13.33333333vw的時候,咱們的1rem 就等於設計稿的100px,就等於咱們css像素的50px了。
此方案只能兼容手機,甚至連ipad兼容都很差,固然,此處的兼容不是兼容問題,是效果問題,只要兼容vw的設備都能用這個方案,可是因爲適配的根本是vw這個, 這個會隨着設備的寬度愈來愈大,那麼用rem作單位的元素也會愈來愈大,以致於若是這個在pc上,那麼無法預覽了,效果會不好,字太大了.這樣咱們能夠設置一下當屏幕過大的時候的狀況,咱們能夠加一句代碼
@media (min-width: 560px) {
html {
font-size: 54px;
}
}
複製代碼
/** * [ 移動端適配方案 ] * @params designWidth 設計稿的實際寬度值,須要根據實際設置 * @params maxWidth 製做稿的最大寬度值,須要根據實際設置 * 例如設計稿爲750,最大寬度爲750,則爲(750,750) * 拿iphone6做爲實驗機: 像素寬度爲 750像素 css寬度爲375px 最終設置html:font-size:50px; 1rem = 50px; 375px = 7.5rem * 若是設計稿是750像素寬的,因爲dpr = 2,因此邏輯像素寬度只有 375 ,那麼設計圖上的 100px 表明 1rem; */
;
(function(designWidth, maxWidth) {
var doc = document,
win = window,
docEl = doc.documentElement, // html節點
remStyle = document.createElement("style"),
tid;
// 計算 rem 比例
function refreshRem() {
// getBoundingClientRect 獲取某個元素相對於視窗的位置集合
var width = docEl.getBoundingClientRect().width; // 獲取整個文檔元素的寬度,iphone6 是 375
maxWidth = maxWidth || 540;
width > maxWidth && (width = maxWidth); // 若是整個視窗的寬度大於 設計稿的最大寬度,那麼就設置寬度爲設計稿的最大寬度,
var rem = ( width / designWidth ) * 100; // 不一樣的手機,width不同,計算 width / designWidth 爲不一樣的比例,好比 iphone6 下 rem = 50px iphone5 下 rem = 42.66666666666667px;
// 利用該效果來實現屏幕小就縮小,屏幕變大就適當的放大
remStyle.innerHTML = 'html{font-size:' + rem + 'px;}';
}
// 將 style 標籤引入
if (docEl.firstElementChild) {
docEl.firstElementChild.appendChild(remStyle); // 頭部head中插入
} else {
var wrap = doc.createElement("div");
wrap.appendChild(remStyle);
doc.write(wrap.innerHTML);
wrap = null;
}
// 要等 wiewport 設置好後才能執行 refreshRem,否則 refreshRem 會執行2次;
refreshRem();
// 手機屏幕尺寸變化
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);
// 文檔所有資源加載完成
// 爲body設置默認字體大小爲16ox
if (doc.readyState === "complete") {
doc.body.style.fontSize = "16px";
} else {
doc.addEventListener("DOMContentLoaded", function(e) {
doc.body.style.fontSize = "16px";
}, false);
}
})(750, 750);
複製代碼
使用方法:
1.複製上面這段代碼到你的頁面的頭部的script標籤的最前面。
2.根據設計稿大小,調整裏面的最後兩個參數值。
3.(這裏假設你的設計稿是750像素)使用1rem=100px
轉換你的設計稿的像素,例如設計稿上某個塊是100px*300px
,換算成rem則爲1rem*3rem
。
demo:
// demo.html
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<!--必需要設置該項-->
<meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
<title></title>
<link rel="stylesheet" href="./index.css">
</head>
<body>
<div class="box">
我是盒子
</div>
<div class="test">
我是盒子
</div>
<script src="./flexible.me.js"></script>
</body>
</html>
複製代碼
既然rem是根據html字體大小來定,咱們咱們徹底也能夠經過css3媒體查詢來完成這部分工做。
@media screen and (min-width:320px) {
html {
font-size: 21.33px
}
body {
font-size: 12px
}
}
@media screen and (min-width:360px) {
html {
font-size: 24px
}
body {
font-size: 12px
}
}
@media screen and (min-width:375px) {
html {
font-size: 25px
}
body {
font-size: 12px
}
}
@media screen and (min-width:384px) {
html {
font-size: 25.6px
}
body {
font-size: 14px
}
}
@media screen and (min-width:400px) {
html {
font-size: 26.67px
}
body {
font-size: 14px
}
}
@media screen and (min-width:414px) {
html {
font-size: 27.6px
}
body {
font-size: 14px
}
}
@media screen and (min-width:424px) {
html {
font-size: 28.27px
}
body {
font-size: 14px
}
}
@media screen and (min-width:480px) {
html {
font-size: 32px
}
body {
font-size: 15.36px
}
}
@media screen and (min-width:540px) {
html {
font-size: 36px
}
body {
font-size: 17.28px
}
}
@media screen and (min-width:720px) {
html {
font-size: 48px
}
body {
font-size: 23.04px
}
}
@media screen and (min-width:750px) {
html {
font-size: 50px
}
body {
font-size: 24px
}
}
複製代碼
像蘇寧易購等網站就是這麼作的:
經過JavaScript讀取屏幕寬度,而後根據寬度計算出對應的尺寸並設置根元素的font-size
。
咱們以320px
的屏幕基準像素爲12px
爲準則。
let htmlwidth = document.documentElement.clientWidth || document.body.clientWidth ; // 獲取文檔寬度
let htmlDom = document.getElementsByTagName('html')[0]; // 獲取htmldom
// 若是頁面寬度太大了的話,保持750
if(htmlwidth>750){ htmlwidth = 750}
// 320px的屏幕基準像素爲12px
htmlDom.style.fontSize= 12 * (htmlwidth / 320) + "px";
複製代碼
使用JS來獲取屏幕寬度的好處在於能夠100%適配全部的機型寬度,由於其元素的基準尺寸是直接算出來的。既然是JS代碼,爲了不形成由於動態設置元素的font-size而形成頁面抖動,通常這部分代碼咱們放在header底部去加載,並內聯到html文檔裏面。
touchstart 手指接觸屏幕時觸發
touchend 手指離開屏幕時觸發
touchmove 已經接觸屏幕的手指開始移動的時候觸發
touchcancel 某種touch事件非正常結束時觸發
複製代碼
有三個TouchList
,一個TouchList
表明一個觸摸平面上全部觸點的列表。
touches
targetTouches
changedTouches
複製代碼
touches
列出全部當前在與觸摸表面接觸的 Touch 對象
targetTouches
包含全部仍與觸摸平面接觸而且touchstart事件與當前事件在同一個目標元素上發生的Touch對象。
changedTouches
用於記錄想要改變最開始接觸摸平面的觸摸對象的touch對象。
經過上圖咱們分析如下:
當只有一個元素的時候,三個touchList都是相同的。
當咱們的目標是div2,一次上來三次觸摸分別爲1,2,3。這時候touches記錄所有的觸摸點,targetTouches,記錄所在目標上的全部觸摸點,changedTouches記錄第一個觸摸點以後的觸摸點。
複製代碼
使用touch事件能夠實現多種效果,好比拖拽,多點觸摸,旋轉手勢等。
clientX:65 // 觸摸點在瀏覽器窗口中的橫座標
clientY:18 // 觸摸點在瀏覽器窗口中的縱座標
force:1 // 觸摸點壓力大小
identifier:0 // 觸摸點惟一標識(ID)
pageX:65 // 觸摸點在頁面中的橫座標
pageY:18 // 觸摸點在頁面中的縱座標
radiusX:11.5 // 觸摸點橢圓的水平半徑
radiusY:11.5 // 觸摸點橢圓的垂直半徑
rotationAngle:0 // 旋轉角度
screenX:560 // 觸摸點在屏幕中的橫座標
screenY:175 // 觸摸點在屏幕中的縱座標
複製代碼
最初的蘋果公司爲了讓用戶能夠在手機上能夠看咱們的頁面,容許用戶雙擊去放大效果,當用戶觸摸第一次以後,會在300ms以內去監聽是否有下一次的觸摸,用來判斷是雙擊操做仍是單擊操做,這就是300ms延遲的由來。
解決辦法有:vue
的fastclick
和react
的react-tap
這兩種。
點擊蒙層(mask)上的關閉按鈕,蒙層消失後發現觸發了按鈕下面元素的click事件蒙層關閉按鈕綁定的是touch事件,而按鈕下邊元素綁定的是click事件,touch事件觸發以後,蒙層消失了,300ms後這個點的click事件fire,event的target天然就是按鈕下面的元素,由於按鈕跟蒙層一塊兒消息了。
解決辦法就是touch和click事件最好不要混用。