摘要:移動端的字體最開始的的方案是升級后的方案以前版本降級使用。在處理移動端邊框的時候有兩種方案,其中一種方案就是將還有一種方案就是通過偽類來處理。固定項欄頁面基本上市面上所看到的移動端的頁面都是固定頭部和底部,少量的會加入側(cè)邊工具欄。
1、移動端的字體
最開始的的方案是:
body {
font-family: "Helvetica Neue", Helvetica, "microsoft yahei", sans-serif;
}
升級后的方案:
body {
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC","Helvetica Neue",STHeiti,"Microsoft Yahei",Tahoma,Simsun,sans-serif;
}
以前iOS版本降級使用 Helvetica。 中文字體設(shè)置為華文黑體STHeiTi, iOS 9+ 就開始支持 -apple-system 參數(shù)了, Chrome 使用 BlinkMacSystemFont ,兼容 iOS/MacOS。 現(xiàn)在很多設(shè)計師的字體都是PingFang,所以這里做了一個兼容。 順便用"Microsoft Yahei"兼容了一下Window系統(tǒng)。 原生 Android 下中文字體與英文字體都選擇默認(rèn)的無襯線字體。 但是因為安卓系統(tǒng)可以去改系統(tǒng)的默認(rèn)字體,而且每一個手機(jī)廠家也會內(nèi)置字體,所以直接讓他去選擇默認(rèn)的吧。不用多帶帶去折騰安卓的字體了。
2、移動端的適配
移動端的適配方案各個廠商都一套方案,但是現(xiàn)在主流的方案是阿里的flexible,具體可以去看下這篇文章: 《使用Flexible實(shí)現(xiàn)手淘H5頁面的終端適配》。 阿里的方案我用過一段時間,但是對于每個device pixel ratio 都要寫一個樣式,雖然可以用sass、less的mixmin用法來處理,但是不同品尺寸屏幕下所顯示的文字個數(shù)不一致的問題(如下圖:商品的標(biāo)題),往往會導(dǎo)致用戶認(rèn)為這是一個bug。 iPhone4的渲染圖
iPhone6的渲染圖
所以后面的開發(fā)就拋棄了這個方案,選中在以前項目中運(yùn)用到的方案,思路是跟淘寶的思路大體上是一樣的,根據(jù)750px的設(shè)計稿來換算成rem,1px == 0.01rem;
CSS單位rem
在W3C規(guī)范中是這樣描述rem的:
font size of the root element.
也就是根節(jié)點(diǎn)的字體的大小,簡單的理解,rem就是相對于根元素的font-size來做計算。而我們的方案中使用rem單位,是能輕易的根據(jù)的font-size計算出元素的盒模型大小。
具體怎么換算呢? 把750px的設(shè)計稿 1px對應(yīng)0.01rem即可
思路:
var html=document.querySelector("html");
html.style.fontSize=html.offsetWidth/7.5+"px"
window.onresize=function(){
var a=document.querySelector("html");a.style.fontSize=a.offsetWidth/7.5+"px";
};
注意:并不是所有的地方都用rem來處理。 移動端的1px邊框。 在處理移動端1px邊框的時候有兩種方案,其中一種方案就是將initial-scale=0.5還有一種方案就是通過偽類來處理。
父級 {
positon: relative;
}
父級:after {
content: " ";
width: 200%;
height: 200%;
position: absolute;
top: -1px;//之所要寫成-1px而不是0是因為這個會將整個框下移1px,所以為了避免整個問題將元素上移1px
left: 0;
z-index: 1;
border: 1px solid #ffffd;
border-bottom: 1px solid #ffffd;
-webkit-transform: scale(0.5);
transform: scale(0.5);
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
}
優(yōu)化后的方案:
;(function(designWidth, rem2px, fixedWidth) {
//容錯
designWidth = designWidth || 750;//傳入設(shè)計稿的寬度
rem2px = rem2px || 100;//rem to px 的關(guān)系
fixedWidth = fixedWidth || 0;//固定最大寬度
//獲取當(dāng)前html文檔
var docEl = document.documentElement;
//獲取body
var body = document.querySelector("body");
//設(shè)置固定寬度的大小
if (!Number(fixedWidth)) {
//不存在固定值,或者固定值為0
body.style.maxWidth = designWidth / rem2px + "rem";
} else {
body.style.maxWidth = fixedWidth / rem2px + "rem";
}
body.style.margin = "auto";
//這里不設(shè)置body的position,為了底部存在可以讓positon:absolute的可以吸在鍵盤上
//屏幕的寬度
var tempWidth = window.screen.width;
var tempHeight = window.screen.height;
//最小的寬度,以這個寬度來渲染,可以保證旋轉(zhuǎn)的時候字體大小不變 為什么不用文檔的寬度, 因為瀏覽器或者默認(rèn)的app有時候會占用導(dǎo)航欄,
//這個時候?qū)挾群透叨染蜁徊眉粢徊糠郑沁@個時候屏幕的寬高是不會因為瀏覽器或者app的導(dǎo)航欄而被裁剪
var minWidth = tempWidth > tempHeight ? tempHeight : tempWidth;
//手機(jī)方向
var orientation = window.orientation;
//獲取當(dāng)前默認(rèn)字體的大小,因為安卓可以設(shè)置默認(rèn)字體的大小來進(jìn)行計算
var tempDom = window.document.createElement("div");
tempDom.style.width = "1rem";
tempDom.style.display = "none";
var head = window.document.getElementsByTagName("head")[0];
head.appendChild(tempDom);
var defaultFontSize = parseFloat(window.getComputedStyle(tempDom, null).getPropertyValue("width"));
tempDom.remove();
//設(shè)置字體的大小
window.onresize = function() {
//延時是因為屏幕旋轉(zhuǎn)獲取新的高度需要一定的時間去重新獲取高度和寬度
setTimeout(function() {
if (typeof(orientation) == "undefined") {
//如果不支持orientation 那么就根據(jù)屏幕的寬高來判斷
var newWidth = window.screen.width;
if (newWidth != tempWidth) {
tempWidth = newWidth
//如果屏幕的寬度值改變了
ReSetFontSize();
}
}
else {
if (orientation != window.orientation) {
//設(shè)置最新的屏幕方向 為什么要延遲,因為文檔去重新并且渲染高度是有一個時間段的
orientation = window.orientation;
ReSetFontSize();
}
}
}, 100);
};
function ReSetFontSize() {
//設(shè)置body的高度,body的高度不能直接設(shè)置成100%會導(dǎo)致重繪,同時為了防止fiex的bug(鍵盤彈出)
body.style.height = docEl.clientHeight + "px";
//設(shè)置字體大小
docEl.style.fontSize = minWidth / designWidth * rem2px / defaultFontSize * 100 + "%";
}
ReSetFontSize();
document.body.classList.remove("vhidden");
})(750, 100, 750);
3、移動端的line-height
為什么這個要多帶帶講呢,因為這個問題在移動端出現(xiàn)的幾率是100%,寫習(xí)慣了PC端頁面的開發(fā)者剛開始上手移動端經(jīng)常會遇到文本垂直居中的問題,明明在谷歌模擬器里面看到文本是垂直居中的,但是為什么在手機(jī)上看到文字向上偏移的,而且安卓的問題比較大。transform雖然可以實(shí)現(xiàn),但是感覺寫起來卻非常的繁瑣。 提供兩種方法, 1、padding
p{
/*高度為90px*/
font-size: .26rem;
padding: 0.22rem;
}
雖然上面的方法可以實(shí)現(xiàn),但是用起來的時候經(jīng)常每次都要去計算高度(padding值等于設(shè)計高度減去font-size之后再/2),這樣就比較麻煩,而且,在針對多行的時候還得計算,于是我又采用了下面的方式。 利用 css3 flex布局的特性。
p{
font-size: .26rem;
height: 0.9rem;
display: flex;
display: -webkit-flex;
-webkit-align-items:center;
align-items:center;
box-pack-align: center;
-webkit-box-pack-align: center;
}
//同時水平居中也可以用下面的css3屬性
box-pack: center;
-webkit-box-pack: center;
-webkit-justify-content: center;
justify-content: center;
4、移動端的布局
移動端的布局情況有點(diǎn)多, 切記移動端最好不要使用postion:fixed,因為這個屬性會在ios下產(chǎn)生很多bug。最終我根據(jù)之前的項目經(jīng)驗簡單做了以下2種分類:
無固定欄頁面
什么叫無固定項,所謂的無固定項頁面就是整個網(wǎng)頁從上到下沒有沒有固定在頁面上的按鈕,頭部沒有固定的按鈕,底部沒有固定的按鈕,左右兩側(cè)也沒有側(cè)邊欄。用戶唯一的操作就是滑動頁面到底部。這一類直接跟寫PC一樣的寫法就行了。
固定項欄頁面
基本上市面上所看到的移動端的頁面都是固定頭部和底部,少量的會加入側(cè)邊工具欄。這里主要講固定頭部和底部的。 下面的例子主要把頁面分為頭部,內(nèi)容,底部三部分。
test
這是內(nèi)容部分1
這是內(nèi)容部分2
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
這是內(nèi)容部分
Phone手機(jī)在滑動overflow-y: scroll的元素上滑動的時候會頓卡,需要加入如下的css代碼就可以了
-webkit-overflow-scrolling:touch;
上面的demo在中間部門有輸入框并且在底部的時候去點(diǎn)擊輸入框,彈出的鍵盤會把輸入框蓋住,只有在輸入部分內(nèi)容之后輸入框才會出現(xiàn)在視窗中。遇到這種情況需要加入如下代碼。
var element = document.getElementById("box");
element.scrollIntoView();
//element.scrollIntoView(false);
//scrollIntoView 可選參數(shù)是 true false,默認(rèn)是true
//true 元素的頂端將和其所在滾動區(qū)的可視區(qū)域的頂端對齊。
//false 元素的底端將和其所在滾動區(qū)的可視區(qū)域的底端對齊。
5、移動端的bfc
這個bfc不是格式化上下文,而是back forward cache(往返緩存),這個特性最早出現(xiàn)在Firefox和Opera瀏覽器上,可以在用戶使用瀏覽器的“后退”和“前進(jìn)”按鈕時加快頁面的轉(zhuǎn)換速度。 原理就是瀏覽器會把之前訪問的頁面緩存到瀏覽器內(nèi)存里面,當(dāng)用在進(jìn)行“后退”和“前進(jìn)”操作的時候,瀏覽器會直接從緩存里面把頁面展現(xiàn)到前臺,從而不去刷新頁面。 但是這樣會導(dǎo)致用戶在子頁面與上一個頁面之前存在管理的時候,操作后返回上個頁面的狀態(tài)并沒有更改。 這個時候我們就需要去檢測頁面是不是從緩存里面讀取出來的頁面。
$(window).on("pageshow", function(event) {
if (event.persisted) {
location.reload(true);
}
});
或者
window.addEventListener("pageshow", funtion(event){
if (event.persisted) {
location.reload(true);
}
});
6、移動端與客戶端的交互
現(xiàn)在內(nèi)嵌H5開發(fā)的頁面越來越多,前端跟客戶端的交互也就越來越多,現(xiàn)在運(yùn)用得最多的方式是用JSBridge 來通信,其主要原理就是就是通過某種方式觸發(fā)一個url(iframe) 的改變,原生捕獲到url,進(jìn)行分析,得到自己想要的數(shù)據(jù)信息。 之所以要考慮用JSBridge 來通信是考慮到Android4.2 以下,addJavascriptInterface 方式有安全漏掉 iOS7以下,無法用到ios提供給前端最新的api messageHandlers 因為現(xiàn)有的手機(jī)基本上都是4.2以上以及iOS7以上,所以我們可以放心大膽使用上面兩個屬性。
var ua = navigator.userAgent.toLowerCase();
window.isAndroid = /android/.test(ua);
window.HtmlWebviewCallNative = function(par) {
if (/客戶端ua標(biāo)識/.test(ua)) {
//判斷是否在客戶端打開的頁面
if (isAndroid) {
//Android這個是安卓向瀏覽器注入的對象,這個看安卓客戶端給的是什么
Android.HTMLCallNative(JSON.stringify(par));
} else {
window.webkit.messageHandlers.HTMLCallNative.postMessage(par);
}
} else {
console.log(JSON.stringify(par))
}
};
//調(diào)用方法eg
HTMLCallNative({
functionName: "callPhone",
params: ["13883785984", "18323270482"],
callback: "callbackFunctionName"
});
原理以及參數(shù)說明 1.通過向window 注冊一個名字為HTMLCallNative 的對象,以后每次向這個函數(shù)傳遞要通信的函數(shù)名和函數(shù)所需的參數(shù)即可;安卓是通過addJavascriptInterface 直接注入頁面,ios是通過WKWebView 的新特性MessageHandler 來這個對象來實(shí)現(xiàn)JS調(diào)用原生方法。 2.約定HTMLCallNative 這個方法名為app中默認(rèn)用來接受新交互規(guī)則的入口函數(shù),安卓和ios分別拿到HTMLCallNative 傳過來的function 名字和參數(shù)。 3.客戶端通過反射機(jī)制,查找字符串函數(shù)名對應(yīng)的函數(shù)并執(zhí)行函數(shù),此時通信成功。 4.functionName : 必為字符串,駝峰式命名,這個字符串為真正調(diào)用的方法,需要前端跟客戶端共同來定義。 5.params :方法需要的參數(shù),無需對參數(shù)進(jìn)行encodeURI 和encodeURIComponent , 支持字符串,array ,object 。 6.callback : 有回調(diào)函數(shù)時,傳入這個參數(shù),只需要傳入函數(shù)名稱即可,若回調(diào)函數(shù)需要傳入?yún)?shù),app端在調(diào)用的時候傳入即可,跟當(dāng)時業(yè)務(wù)相關(guān),這里就不約定格式了。
相比JSBridge 的優(yōu)點(diǎn): 1.在JS中寫起來簡單,不用再用創(chuàng)建iframe 然后觸發(fā)URL的方式那么麻煩了。 2.JS傳遞參數(shù)更方便。使用攔截URL的方式傳遞參數(shù),只能把參數(shù)拼接在后面,如果遇到要傳遞的參數(shù)中有特殊字符,如&、=、?等,必須得轉(zhuǎn)換,否則參數(shù)解析肯定會出錯。 例如傳遞的url是這樣的: http://www.baidu.com/share/op... 使用攔截URL 的JS調(diào)用方式
loadURL("firstClick://shareClick?title=分享的標(biāo)題&content=分享的內(nèi)容&url=鏈接地址&imagePath=圖片地址"); }
將上面的url 放入鏈接地址這里后,根本無法區(qū)分share_uuid 是其他參數(shù),還是url里附帶的參數(shù)。 但是使用MessageHandler 就可以避免特殊字符引起的問題。
7、移動端喚起手機(jī)app
首先,我們看下安卓的配置文件和Scheme
重點(diǎn)關(guān) ,前端就需要根據(jù)這個字來喚起app
打開app
schema拼接協(xié)議的格式:[scheme]://[host]/[path]?[query] 當(dāng)然ios的也有自己的協(xié)議,通常在寫喚起app之前需要跟客戶端的同事進(jìn)行對接一下,拿到他們的協(xié)議。
注意schema協(xié)議要小寫,否則會有不能響應(yīng)的異常!
當(dāng)然我們可以整合一下代碼,把ios的也加進(jìn)來:
var u = navigator.userAgent;var isAndroid = u.indexOf("Android") > -1 || u.indexOf("Linux") > -1; //android終端或者uc瀏覽器var isiOS2 = !!u.match(/(i[^;]+;( U;)? CPU.+Mac OS X/); //ios終端if (isAndroid) {
window.location.href = "安卓提供協(xié)議url";
/***打開app的協(xié)議,有安卓同事提供***/
window.setTimeout(function() {
window.location.href = "下載的地址";
}, 2000);
} else if (isiOS2) {
window.location.href = "IOS提供協(xié)議url";
/***打開app的協(xié)議,有ios同事提供***/
window.setTimeout(function() {
window.location.href = "下載的地址";
}, 2000);
} else {
window.location.href = "下載的地址";
}
簡單的喚起方法沒有解決在其他應(yīng)用喚起的bug,可以通過下面的喚起 [https://github.com/sunhaikuo/js-arouse-app][4]
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/116825.html