手机端

移动端高清、多屏适配方案–转

吴阳 No Comments

http://div.io/topic/1092

转:说说JSON和JSONP,也许你会豁然开朗

吴阳 One comment

原文地址:http://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html

前言:

由于Sencha Touch 2这种开发模式的特性,基本决定了它原生的数据交互行为几乎只能通过AJAX来实现。

当然了,通过调用强大的PhoneGap插件然后打包,你可以实现100%的Socket通讯和本地数据库功能,又或者通过HTML5的WebSocket也可以实现与服务器的通讯和服务端推功能,但这两种方式都有其局限性,前者需要PhoneGap支持,后者要求用户设备必须支持WebSocket,因此都不能算是ST2的原生解决方案,原生的只有AJAX。

说到AJAX就会不可避免的面临两个问题,第一个是AJAX以何种格式来交换数据?第二个是跨域的需求如何解决?这两个问题目前都有不同的解决方案,比如数据可以用自定义字符串或者用XML来描述,跨域可以通过服务器端代理来解决。

但到目前为止最被推崇或者说首选的方案还是用JSON来传数据,靠JSONP来跨域。而这就是本文将要讲述的内容。

JSON和JSONP虽然只有一个字母的差别,但其实他们根本不是一回事儿:JSON是一种数据交换格式,而JSONP是一种依靠开发人员的聪明才智创造出的一种非官方跨域数据交互协议。我们拿最近比较火的谍战片来打个比方,JSON是地下党们用来书写和交换情报的“暗号”,而JSONP则是把用暗号书写的情报传递给自己同志时使用的接头方式。看到没?一个是描述信息的格式,一个是信息传递双方约定的方法。

既然随便聊聊,那我们就不再采用教条的方式来讲述,而是把关注重心放在帮助开发人员理解是否应当选择使用以及如何使用上。

什么是JSON?

前面简单说了一下,JSON是一种基于文本的数据交换方式,或者叫做数据描述格式,你是否该选用他首先肯定要关注它所拥有的优点。

JSON的优点:

1、基于纯文本,跨平台传递极其简单;

2、Javascript原生支持,后台语言几乎全部支持;

3、轻量级数据格式,占用字符数量极少,特别适合互联网传递;

4、可读性较强,虽然比不上XML那么一目了然,但在合理的依次缩进之后还是很容易识别的;

5、容易编写和解析,当然前提是你要知道数据结构;

JSON的缺点当然也有,但在作者看来实在是无关紧要的东西,所以不再单独说明。

JSON的格式或者叫规则:

JSON能够以非常简单的方式来描述数据结构,XML能做的它都能做,因此在跨平台方面两者完全不分伯仲。

1、JSON只有两种数据类型描述符,大括号{}和方括号[],其余英文冒号:是映射符,英文逗号,是分隔符,英文双引号””是定义符。

2、大括号{}用来描述一组“不同类型的无序键值对集合”(每个键值对可以理解为OOP的属性描述),方括号[]用来描述一组“相同类型的有序数据集合”(可对应OOP的数组)。

3、上述两种集合中若有多个子项,则通过英文逗号,进行分隔。

4、键值对以英文冒号:进行分隔,并且建议键名都加上英文双引号””,以便于不同语言的解析。

5、JSON内部常用数据类型无非就是字符串、数字、布尔、日期、null 这么几个,字符串必须用双引号引起来,其余的都不用,日期类型比较特殊,这里就不展开讲述了,只是建议如果客户端没有按日期排序功能需求的话,那么把日期时间直接作为字符串传递就好,可以省去很多麻烦。

JSON实例:

// 描述一个人
var person = {
 "Name": "Bob",
 "Age": 32,
 "Company": "IBM",
 "Engineer": true
 }
// 获取这个人的信息
var personAge = person.Age;
// 描述几个人
var members = [
 {
 "Name": "Bob",
 "Age": 32,
 "Company": "IBM",
 "Engineer": true
 },
 {
 "Name": "John",
 "Age": 20,
 "Company": "Oracle",
 "Engineer": false
 },
 {
 "Name": "Henry",
 "Age": 45,
 "Company": "Microsoft",
 "Engineer": false
 }
 ]
// 读取其中John的公司名称
var johnsCompany = members[1].Company;
// 描述一次会议
var conference = {
 "Conference": "Future Marketing",
 "Date": "2012-6-1",
 "Address": "Beijing",
 "Members":
 [
 {
 "Name": "Bob",
 "Age": 32,
 "Company": "IBM",
 "Engineer": true
 },
 {
 "Name": "John",
 "Age": 20,
 "Company": "Oracle",
 "Engineer": false
 },
 {
 "Name": "Henry",
 "Age": 45,
 "Company": "Microsoft",
 "Engineer": false
 }
 ]
 }
// 读取参会者Henry是否工程师
var henryIsAnEngineer = conference.Members[2].Engineer;

 

什么是JSONP?

先说说JSONP是怎么产生的:

其实网上关于JSONP的讲解有很多,但却千篇一律,而且云里雾里,对于很多刚接触的人来讲理解起来有些困难,小可不才,试着用自己的方式来阐释一下这个问题,看看是否有帮助。

1、一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准;

2、不过我们又发现,Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>);

3、于是可以判断,当前阶段如果想通过纯web端(ActiveX控件、服务端代理、属于未来的HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理;

4、恰巧我们已经知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据;

5、这样子解决方案就呼之欲出了,web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。

6、客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了,这种获取远程数据的方式看起来非常像AJAX,但其实并不一样。

7、为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

如果对于callback参数如何使用还有些模糊的话,我们后面会有具体的实例来讲解。

JSONP的客户端具体实现:

不管jQuery也好,extjs也罢,又或者是其他支持jsonp的框架,他们幕后所做的工作都是一样的,下面我来循序渐进的说明一下jsonp在客户端的实现:

1、我们知道,哪怕跨域js文件中的代码(当然指符合web脚本安全策略的),web页面也是可以无条件执行的。

远程服务器remoteserver.com根目录下有个remote.js文件代码如下:
alert(‘我是远程文件’);
本地服务器localserver.com下有个jsonp.html页面代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
 <title></title>
 <script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>
<body>
</body>
</html>

毫无疑问,页面将会弹出一个提示窗体,显示跨域调用成功。
2、现在我们在jsonp.html页面定义一个函数,然后在远程remote.js中传入数据进行调用。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
 <title></title>
 <script type="text/javascript">
 var localHandler = function(data){
 alert('我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:' + data.result);
 };
 </script>
 <script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>
<body>
</body>
</html>
remote.js文件代码如下:
localHandler({"result":"我是远程js带来的数据"});

运行之后查看结果,页面成功弹出提示窗口,显示本地函数被跨域的远程js调用成功,并且还接收到了远程js带来的数据。很欣喜,跨域远程获取数据的目的基本实现了,但是又一个问题出现了,我怎么让远程js知道它应该调用的本地函数叫什么名字呢?毕竟是jsonp的服务者都要面对很多服务对象,而这些服务对象各自的本地函数都不相同啊?我们接着往下看。

3、聪明的开发者很容易想到,只要服务端提供的js脚本是动态生成的就行了呗,这样调用者可以传一个参数过去告诉服务端“我想要一段调用XXX函数的js代码,请你返回给我”,于是服务器就可以按照客户端的需求来生成js脚本并响应了。

看jsonp.html页面的代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
// 得到航班信息查询结果后的回调函数
var flightHandler = function(data){
alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
};
// 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";
// 创建script标签,设置其属性
var script = document.createElement('script');
script.setAttribute('src', url);
// 把script标签加入head,此时调用开始
document.getElementsByTagName('head')[0].appendChild(script);
</script>
</head>
<body>

</body>
</html>

这次的代码变化比较大,不再直接把远程js文件写死,而是编码实现动态查询,而这也正是jsonp客户端实现的核心部分,本例中的重点也就在于如何完成jsonp调用的全过程。

我们看到调用的url中传递了一个code参数,告诉服务器我要查的是CA1998次航班的信息,而callback参数则告诉服务器,我的本地回调函数叫做flightHandler,所以请把查询结果传入这个函数中进行调用。

OK,服务器很聪明,这个叫做flightResult.aspx的页面生成了一段这样的代码提供给jsonp.html(服务端的实现这里就不演示了,与你选用的语言无关,说到底就是拼接字符串):

flightHandler({
    "code": "CA1998",
    "price": 1780,
    "tickets": 5
});

我们看到,传递给flightHandler函数的是一个json,它描述了航班的基本信息。运行一下页面,成功弹出提示窗口,jsonp的执行全过程顺利完成!

4、到这里为止的话,相信你已经能够理解jsonp的客户端实现原理了吧?剩下的就是如何把代码封装一下,以便于与用户界面交互,从而实现多次和重复调用。

什么?你用的是jQuery,想知道jQuery如何实现jsonp调用?好吧,那我就好人做到底,再给你一段jQuery使用jsonp的代码(我们依然沿用上面那个航班信息查询的例子,假定返回jsonp结果不变):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Untitled Page</title>
<script type="text/javascript" src=jquery.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function(){
$.ajax({
type: "get",
async: false,
url: "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998",
dataType: "jsonp",
jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
success: function(json){
alert('您查询到航班信息:票价: ' + json.price + ' 元,余票: ' + json.tickets + ' 张。');
},
error: function(){
alert('fail');
}
});
});
</script>
</head>
<body>
</body>
</html>

是不是有点奇怪?为什么我这次没有写flightHandler这个函数呢?而且竟然也运行成功了!哈哈,这就是jQuery的功劳了,jquery在处理jsonp类型的ajax时(还是忍不住吐槽,虽然jquery也把jsonp归入了ajax,但其实它们真的不是一回事儿),自动帮你生成回调函数并把数据取出来供success属性方法来调用,是不是很爽呀?

补充:

1、ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装;

2、但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本。

3、所以说,其实ajax与jsonp的区别不在于是否跨域,ajax通过服务端代理一样可以实现跨域,jsonp本身也不排斥同域的数据的获取。

4、还有就是,jsonp是一种方式或者说非强制性协议,如同ajax一样,它也不一定非要用json格式来传递数据,如果你愿意,字符串都行,只不过这样不利于用jsonp提供公开服务。

总而言之,jsonp不是ajax的一个特例,哪怕jquery等巨头把jsonp封装进了ajax,也不能改变着一点!

rem的用法

吴阳 No Comments

原文地址:http://www.w3cfuns.com/blog-5471969-5407429.html

1、简单暴力的办法

<meta name="viewport" content="width=320,maximum-scale=1.3,user-scalable=no">

以320宽度为基准,进行缩放,最大缩放为320*1.3 = 416,基本缩放到426都就可以兼容iphone6 plus的屏幕了,这个方法简单粗暴,又高效。

2、使用rem

<!DOCTYPE html>
<html lang="zh">
<head>
 <meta charset="UTF-8">
 <title>rem phone test</title>
 <meta name="viewport" content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
 <style>
 html {
 height: 100%;
 width: 100%;
 font-family: 'Heiti SC', 'Microsoft YaHei';
 font-size: 5px;
 overflow: hidden;
 outline: 0;
 -webkit-text-size-adjust:none;
 }
 body {
 height: 100%;
 margin: 0;
 overflow: hidden;
 -webkit-user-select: none;
 position: relative;
 }
 header,
 footer {
 width: 100%;
 line-height: 1.5rem;
 font-size: 1rem;
 color: #000;
 border: 1px solid #ccc;
 text-align: center;
 background-color: #ccc;
 }
 .bd {
 margin-top: 1rem;
 margin-bottom: .5rem;
 margin-right: -.5rem;
 font-size: 0;
 }
 .box {
 width: 5rem;
 height: 5rem;
 display: inline-block;
 margin-right:.5rem;
 margin-bottom: .5rem;
 }
 .blue-box {
 background-color: #06c;
 }
 .org-box {
 background-color: #1fc195;
 }
 </style>
 
</head>
<body>
<header>我是头部</header>
 <div class="bd">
 <div class="box blue-box"></div>
 <div class="box org-box"></div>
 <div class="box blue-box"></div>
 <div class="box org-box"></div>
 <div class="box blue-box"></div>
 <div class="box org-box"></div>
 </div>
 <footer>我是页脚</footer>
 <script>
 (function (doc, win) {
 var docEl = doc.documentElement,
 resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
 recalc = function () {
 var clientWidth = docEl.clientWidth;
 if (!clientWidth) return;
 docEl.style.fontSize = 20 * (clientWidth / 320) + 'px';
 };
if (!doc.addEventListener) return;
 win.addEventListener(resizeEvt, recalc, false);
 doc.addEventListener('DOMContentLoaded', recalc, false);
 })(document, window);
 </script>
</body>
</html>

以上是原文作者根据不同分辨率设定根元素字体大小的JS,实现了,在不同分辨率下大小/布局等比例显示的效果。

关系:rem是以根元素作为参照。

比如

html{font-size:10px;}     1rem=10px;

html{font-size:20px;}    1rem=20px;

………..

所以只要根据不同设备设定不同根元素的字体大小,那么就可以适应不同的设备了。

那么怎么计算出不同分辨率下font-size的值?

1418903956

上面的表格蓝色一列是demo的尺寸,页面是以640的宽度去切的,怎么计算不同宽度下font-size的值,大家看表格上面的数值变化应该能明白。举个例子:384/640 = 0.6,384是640的0.6倍,所以384页面宽度下的font-size也等于它的0.6倍,这时384的font-size就等于12px。在不同设备的宽度计算方式以此类推。

既然可以用JS实现,也可以用CSS实现。下面用到的是media。

html {
 font-size : 20px;
}
@media only screen and (min-width: 401px){
 html {
 font-size: 25px !important;
 }
}
@media only screen and (min-width: 428px){
 html {
 font-size: 26.75px !important;
 }
}
@media only screen and (min-width: 481px){
 html {
 font-size: 30px !important; 
 }
}
@media only screen and (min-width: 569px){
 html {
 font-size: 35px !important; 
 }
}
@media only screen and (min-width: 641px){
 html {
 font-size: 40px !important; 
 }
}

上面的做的设置当然是不能所有设备全适配,但是用JS是可以实现全适配。具体用哪个就要根据自己的实际工作场景去定了。

 

关于适配你需要知道的—MobileWeb适配总结

吴阳 No Comments

原文地址:http://mobile.51cto.com/ahot-481934.htm

开门见山,本篇将总结一下MobileWeb的适配方法,即我们常说的H5页面、手机页面、WAP页、webview页面等等。

本篇讨论的页面指专门针对手机设备设计的页面,并非兼容全设备的响应式布局。 文中提到的 device-width 指 viewport meta 标签中 width 的值,即由浏览器指定的值,常用机型对应值可参照Screen Sizes。

适配达到的效果是什么?

在不同尺寸的手机设备上,页面“相对性的达到合理的展示(自适应)”或者“保持统一效果的等比缩放(看起来差不多)”。

适配应关注哪些要素?

一般来说,我们需要关注的是:字体、高宽间距、图像(图标、图片)。

其中,图像相对要复杂一些,针对流量、清晰度等问题网上也有比较成熟的解决方案,比如:矢量化、字体化、image-set 等等,在此不做深入。在满足快速开发的需求下,我们使用较为偷懒的方式:利用 css 将图像限定在元素内( img 图片使用 [max-]width: 100% ,背景图像使用 background-size ),布局只针对元素进行。

另外要考虑到,设计师设计视觉稿时使用什么样的宽度,才能既满足设计自身的需求又能让前端开发方便的切图适配。

举个例子

围绕这三要素,我们用一个小例子来说明接下来要介绍的三种方案的实现方式,按 640px 标准需实现的效果如图:

app.jpg

固定高度,宽度自适应

这是目前最通用的一种做法,属于自适应布局,viewport width 设置为 device-width,以较小宽度(如 320px)的视觉稿作为参照进行布局。垂直方向的高度和间距使用定值,水平方向混合使用定值和百分比或者利用弹性布局,最终达到“当手机屏幕变化时,横向拉伸或者填充空白的效果”。图像元素根据容器情况,使用定值或者 background-size 缩放。

粗略浏览了下一些大厂的首页,像百度、腾讯、Facebook、Twitter 都是采用的这种方案。

要点:

以小宽度作为参照是因为如果布局满足了小宽度的摆放,当屏幕变宽时,简单的填充空白就可以了;而如果反过来就可能造成“挤坏了”,考虑 header 区域,左测 logo 右测横向 nav 的情况。

需要小宽度的布局,又需要大宽度的图像,这是一个矛盾点。

320px 过于窄小,不利于页面的设计;只能设计横向拉伸的元素布局,存在很多局限性。

兼容性较好。

实现比较简单,样式中的尺寸都按照视觉稿二分之一大小设置,查看效果和代码。

固定宽度,viewport 缩放

视觉稿、页面宽度、viewport width 使用统一宽度,利用浏览器自身缩放完成适配。页面样式(包括图像元素)完全按照视觉稿的尺寸,使用定值单位 (px、em)即可完成。

优点:

开发简单:缩放交给浏览器,完全按视觉稿切图。

还原精准:绝对等比例缩放,可以精准还原视觉稿(不考虑清晰度的情况下)。

测试方便:在PC端即可完成大部分测试,手机端只需酌情调整一些细节(比如图标、字体混合排列时,因为字体不同造成的对齐问题)。

存在的问题:

像素丢失:对于一些分辨率较低的手机,可能设备像素还未达到指定的 viewport 宽度,此时屏幕的渲染可能就不准确了。比较常见的是边框“消失”了,不过随着手机硬件的更新,这个问题会越来越少的。

缩放失效:某些安卓机不能正常的根据 meta 标签中 width 的值来缩放 viewport,需要配合 initial-scale 。

文本折行:存在于缩放失效的机型中,某些手机为了便于文本的阅读,在文本到达 viewport 边缘(非元素容器的边缘)时即进行折行,而当 viewport 宽度被修正后,浏览器并没有正确的重绘,所以就发现文本没有占满整行。一些常用的段落性文本标签会存在该问题。

缩放失效问题需通过 js 动态设定 initial-scale

1

  1. var fixScreen = function() {
  2. var metaEl = doc.querySelector(‘meta[name=”viewport”]’),
  3. metaCtt = metaEl ? metaEl.content : ,
  4. matchScale = metaCtt.match(/initial\-scale=([\d\.]+)/),
  5. matchWidth = metaCtt.match(/width=([^,\s]+)/);
  6. if ( metaEl && !matchScale && ( matchWidth && matchWidth[1] != ‘device-width’) ) {
  7. var width = parseInt(matchWidth[1]),
  8. iw = win.innerWidth || width,
  9. ow = win.outerWidth || iw,
  10. sw = win.screen.width || iw,
  11. saw = win.screen.availWidth || iw,
  12. ih = win.innerHeight || width,
  13. oh = win.outerHeight || ih,
  14. ish = win.screen.height || ih,
  15. sah = win.screen.availHeight || ih,
  16. w = Math.min(iw,ow,sw,saw,ih,oh,ish,sah),
  17. scale = w / width;
  18. if ( ratio < 1) {
  19. metaEl.content += ‘,initial-scale=’ + ratio + ‘,maximum-scale=’ + ratio + ‘, minimum-scale=’ + scale + ‘,user-scalable=no’;
  20. }
  21. }
  22. }

文本折行问题可以通过 css

文本折行问题可以通过 css 样式解决。

既然该方案使用固定宽度值,那么这个值是多少合适呢?首要考虑的是主流分辨率,可参考Screen Sizes和友盟指数的数据;其次要考虑设计部门常用的设计尺寸,综合协调,最终确定一个合适的值。

该处使用640px来实现例子,查看效果和代码。

利用 rem 布局

依照某特定宽度设定 rem 值(即 html 的 font-size),页面任何需要弹性适配的元素,尺寸均换算为 rem 进行布局;当页面渲染时,根据页面有效宽度进行计算,调整 rem 的大小,动态缩放以达到适配的效果。利用该方案,还可以根据 devicePixelRatio 设定 initial-scale 来放大 viewport,使页面按照物理像素渲染,提升清晰度。

优点:

清晰度高,能达到物理像素的清晰度。

能解决 DPR 引起的“1像素”问题。

向后兼容较好,即便屏幕宽度增加、PPI 增加该方案依旧适用。

缺点:

适配 js 需尽可能早进入,减少(避免)viewport 变化引起的重绘。

某些Android机会丢掉 rem 小数部分。

需要预编译库进行单位转换。

开发时,css 及 js 都以 16px 作为基数换算 rem,借助预编译库(以 scss 为例),我们设定一个动态尺寸单位 $ppr: 750px/16px/1rem ,即 pixel per rem,任何使用弹性尺寸的地方写作:width: 100px/$ppr。

动态调整 rem 的方法如下:

02

  1. var fixScreen = function() {
  2. var metaEl = doc.querySelector(‘meta[name=”viewport”]’),
  3. metaCtt = metaEl ? metaEl.content : ,
  4. matchScale = metaCtt.match(/initial\-scale=([\d\.]+)/),
  5. matchWidth = metaCtt.match(/width=([^,\s]+)/);
  6. if ( !metaEl ) { // REM
  7. var docEl = doc.documentElement,
  8. maxwidth = docEl.dataset.mw || 750// 每 dpr 最大页面宽度
  9. dpr = isIos ? Math.min(win.devicePixelRatio, 3) : 1,
  10. scale = 1 / dpr,
  11. tid;
  12. docEl.removeAttribute(‘data-mw’);
  13. docEl.dataset.dpr = dpr;
  14. metaEl = doc.createElement(‘meta’);
  15. metaEl.name = ‘viewport’;
  16. metaEl.content = fillScale(scale);
  17. docEl.firstElementChild.appendChild(metaEl);
  18. var refreshRem = function() {
  19. var width = docEl.getBoundingClientRect().width;
  20. if (width / dpr > maxwidth) {
  21. width = maxwidth * dpr;
  22. }
  23. var rem = width / 16;
  24. docEl.style.fontSize = rem + ‘px’;
  25. };
  26. //…
  27. refreshRem();
  28. }
  29. }

代码实现主要参考淘宝网触屏版的适配方法,查看效果和代码,其中 scss 的写法可以参见这里。

注意,较小的背景图(比如一些 icon)的 background-size 不要使用具体 rem 数值,裁剪后会出现边缘丢失。应使用与元素等尺寸切图,设定 background-size: cover|contain 来缩放。

总结

总的来看,目前还没有完美的解决方案,这些也只是尽可能的满足快速开发、简单适配需求的通用方案。其中对于一些较为细节的问题(比如字体的点阵尺寸、非弹性的定值需求)未做讨论。实际开发过程中,更应该综合考虑项目类型、资源成本、人员配合等多方面的因素,选择合适的方案。

代码实现中使用到的 mobile-util.js 对定宽和 rem 适配进行了整合,源码在此。

【责任编辑:chenqingxiang TEL:(010)68476606】

移动端meta

吴阳 No Comments

<meta content="text/html; charset=utf-8" http-equiv="Content-Type"> //文本为UTF-8
<meta charset="utf-8"> //编码为UTF-8
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"> 
//width - viewport的宽度 height - viewport的高度 initial-scale - 初始的缩放比例 minimum-scale - 允许用户缩放到的最小比例 maximum-scale - 允许用户缩放到的最大比例 user-scalable - 用户是否可以手动缩放
<meta content="yes" name="apple-mobile-web-app-capable"> 
//网站开启对web app程序的支持
<meta content="black" name="apple-mobile-web-app-status-bar-style"> 
//在 web app 应用下状态条(屏幕顶部条)的颜色;默认值为 default(白色),可以定为 black(黑色)和 black-translucent(灰色半透明)
<meta content="telephone=no" name="format-detection">
//使设备浏览网页时对数字不启用电话功能(不同设备解释不同,iTouch 点击数字为存入联系人,iPhone 为拨打电话),忽略将页面中的数字识别为电话号码。若需要启用电话功能将 telephone=yes 即可,若在页面上面有 Google Maps, iTunes 和 YouTube 的链接会在ios设备上打开相应的程序组件。

http-equiv
属性为名称/值对提供了名称。并指示服务器在发送实际的文档之前先在要传送给浏览器的 MIME 文档头部包含名称/值对。
当服务器向浏览器发送文档时,会先发送许多名称/值对。虽然有些服务器会发送许多这种名称/值对,但是所有服务器都至少要发送一个:content-type:text/html。这将告诉浏览器准备接受一个 HTML 文档。
使用带有 http-equiv 属性的标签时,服务器将把名称/值对添加到发送给浏览器的内容头部.
重定向
<meta http-equiv=”Refresh” content=”5;url=http://www.w3school.com.cn” />
释义:您将在 5 秒内被重定向到新的地址。