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