移动Web App开发

移动Web基础知识

移动开发像素((Pixel)知识

css的一个像素只是一个抽象的单位,在不同的设备中代表的设备物理像素是不同的。

  • px:css pixels,逻辑像素,浏览器使用的抽象单位;
  • dp,pt:device independent pixels,设备无关像素,物理像素
  • dpr:devicePixelRatio,设备像素缩放比
    计算公式:1px=(dpr)^2 dp
    1px = dpr ^2
    dp 是平面上的像素换算,但实际开发当中使用更多的是长度上的换算:
    1px = dpr * dp。
  • DPI:打印机每英寸可以喷的墨汁点(印刷行业)
  • PPI:屏幕每英寸像素数量,即 每英寸像素密度
    比如手机分辨率是1920*1080 手机尺寸5英寸
    ppi=开方(1920^2+1080^2) /5
  • Retina屏(高清屏):dpr都是>=2
    1

Viewport视图

没有viewport,直接渲染,会使得排版混乱。viewport提供一个虚拟的页面来渲染文档,然后再缩放比例。

Viewport Meta标签:

移动Web最佳viewport设置:
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">

  • width:设置布局viewport的特定值(“device-width”)
  • initial-scale:设置页面的初始缩放
  • minimum-scale:最小缩放
  • maximum-scale:最大缩放
  • user-scalable:用户能否缩放

设计移动Web

方案一: 根据设备的实际宽度来设计(常用)
手机宽320px, 我们就拿320px设计
方案二: 1px = 1dp
缩放0.5, 根据设备的物理像素dp等于抽象像素px来设计. 1像素边框和高清图都不需要额外处理.

高效的移动Web布局

Flexbox弹性盒子布局

不定宽高的水平垂直居中布局

1
2
3
4
5
6
.wrapper{
position:absolute;
top:50%;
left:50%;
transform:translate(-50%,-50%);
}

flexbox版-不定宽高的水平垂直居中布局

1
2
3
4
5
.parent{
justify-content:center;//子元素水平居中
align-items:center;//子元素垂直居中
display:-webkit-flex;
}

Flexbox弹性布局属性:
  • flex:flex伸缩布局;display:-webkit-flex;
  • flex-direction: 伸缩流方向:row/column/row-reverse/column-reverse
  • flex-wrap:伸缩换行,nowrap/wrap/wrap-reverse
  • flex-flow:伸缩流方向与换行,flex-direction和flex-wrap属性的缩写版本。
  • justify-content:主轴对齐方式:flex-start/flex-end/center/space-between/space-around
  • align-items:伸缩项目行在侧轴对齐方式:flex-start/flex-end/center/stretch/baseline
  • align-self:伸缩项目自身在侧轴对齐方法:flex-start/flex-end/center/baseline/stretch
  • align-content:堆栈伸缩行,伸缩行在侧轴对齐方式:flex-start/flex-end/center/space-between/space-around/stretch
  • order:显示顺序:
  • flex:伸缩性(伸缩项目的宽度/高度自动填充伸缩容器额外空间):包含3个参数:flex-grow(扩展比率,默认0)/flex-shrink(收缩比率,默认1)/flex-basis(伸缩基准值,默认auto)

Flexbox弹性盒子布局-兼容性
iOS可以使用最新的flex布局
android4.4以下,只能兼容旧版flexbox布局
android4.4及以上,可以使用最新flex布局。

响应式布局

响应式布局:可以让一个网站兼容不同分辨率的设备,给用户更好的视觉使用体验。
格式:@media 媒体类型 and (媒体特性){你的样式}

1
2
3
4
5
@media screen and (max-width:480px){
.ads {
display:none;
}
}

媒体类型:

  • Screen-屏幕
  • print-打印机
  • handheld-手持设备
  • all-通用

常用媒体查询参数:

  • device-width,device-height 屏幕宽高,物理
  • width,height 渲染窗口宽度,可视
  • orientation 设备方向,竖屏(portrait)和横屏(landscape)展示的区别对待
  • resolution 设备分辨率,不同于像素

响应式设计要点:
设计点1:百分比布局
设计点2:弹性图片:img {max-width:100%;}
设计点3:重新布局,显示与隐藏

移动Web特别样式处理

高清图片

在移动web页面上渲染图片,为了避免图片产生模糊,图片的宽高应该用物理像素单位渲染,即100*100的图片,应该使用100dp*100dp.
width:(w_value/dpr)px;
height:(h_value/dpr)px;

一像素边框

同样是retina屏幕下的问题,根本原因1px使用2dp渲染
解决方法:scaleY(.5)

1
2
3
4
5
6
7
8
9
.itemList li + li:before{
position: absolute;
top: -1px;
left: 0px;
content: '';
width: 100%;
height: 1px;
border-top: 1px solid #d1d1d1;
-webkit-transform: scaleY(0.5);

相对单位rem

为了适应各大屏幕的手机,px略显固定,不能根据尺寸的大小而改变,使用相对单位更能体验页面兼容性

em:根据父节点的font-size为相对单位
rem:根据html的font-size为相对单位
em在多层嵌套下变得非常难以控制;rem更加能够作为全局统一设置的度量
不使用rem的情况:font-size(字体大小)

多行文本溢出

单行文本溢出

1
2
3
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;

多行文本溢出
1、WebKit浏览器或移动端的页面
在WebKit浏览器或移动端(绝大部分是WebKit内核的浏览器)的页面实现比较简单,可以直接使用WebKit的CSS扩展属性(WebKit是私有属性)-webkit-line-clamp 。
-webkit-line-clamp用来限制在一个块元素显示的文本的行数。 为了实现该效果,它需要组合其他的WebKit属性。
常见结合属性:

  • display: -webkit-box; 必须结合的属性 ,将对象作为弹性伸缩盒子模型显示 。
  • -webkit-box-orient 必须结合的属性 ,设置或检索伸缩盒对象的子元素的排列方式 。
  • text-overflow:ellipsis;,可以用来多行文本的情况下,用省略号“…”隐藏超出范围的文本 。
    1
    2
    3
    4
    5
    6
    display: -webkit-box !important;
    overflow: hidden;
    text-overflow: ellipsis;

    -webkit-box-orient: vertical; // 方向垂直
    -webkit-line-clamp: 2; // 自动截断显示2行

2、跨浏览器兼容的方案:
设置相对定位的容器高度,用包含省略号(…)的元素模拟实现;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.tab-paragraph {
position: relative;
line-height: 1.4em;
height: 4.2em;//高度=行高*行数
overflow: hidden;
.tab-paragraph::after {
content: "...";
position: absolute;
bottom: 0;
right: 0;
font-weight: 600;
padding: 0 1px 1px 5px;
background: linear-gradient(to right,transparent,#fff 55%);
}

参考链接:多行文本溢出显示省略号(…)全攻略

常用的Web App布局

1、流式布局:
在页面布局的时候都是通过百分比来定义宽度,但是高度大都是用px来固定住,所以在大屏幕的手机下显示效果会变成有些页面元素宽度被拉的很长,但是高度还是和原来一样,实际显示非常的不协调,这就是流式布局的最致命的缺点,往往只有几个尺寸的手机下看到的效果是令人满意的。
流式布局并不是最理想的实现方式,通过大量的百分比布局,会经常出现许多兼容性的问题,还有就是对设计有很多的限制,因为他们在设计之初就需要考虑流式布局对元素造成的影响,只能设计横向拉伸的元素布局,设计的时候存在很多局限性。

2、固定宽度做法
早期有些网站把页面设置成320的宽度,超出部分留白,这样做视觉,前端都挺开心,视觉在也不用被流式布局限制自己的设计灵感了,前端也不用在搞坑爹的流式布局。
这种解决方案也是存在一些问题,例如在大屏幕手机下两边是留白的,还有一个就是大屏幕手机下看起来页面会特别小,操作的按钮也很小,手机淘宝首页起初是这么做的,但近期改版了,采用了rem。

3.响应式做法
响应式这种方式在国内很少有大型企业的复杂性的网站在移动端用这种方法去做,主要原因是工作大,维护性难,所以一般都是中小型的门户或者博客类站点会采用响应式的方法从web page到web app直接一步到位,因为这样反而可以节约成本,不用再专门为自己的网站做一个web app的版本。

4.设置viewport进行缩放
天猫的web app的首页就是采用这种方式去做的,以320宽度为基准,进行缩放,最大缩放为320*1.3 = 416,基本缩放到416都就可以兼容iphone6 plus的屏幕了,这个方法简单粗暴,又高效。
缺点:缩放会导致有些页面元素模糊的情况。
例如:以最小的屏幕(iPhone)做一版数据出来,然后通过js去控制
viewport 的 initial-scale (网页缩放比例)。
如:iPhone4下:

1
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0 />

那么对应的到了iPhone6需要调整缩放比例 initial-scale=375/320 =1.18

1
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.18 />

同理到了iPhone6 Plus对应的应该是 initial-scale=414/320 =1.30

1
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=3.

5、Rem布局适配所有屏幕
rem是通过根元素进行适配的,网页中的根元素指的是html我们通过设置html的字体大小就可以控制rem的大小。
例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
html{
font-size:20px;
}
.btn {
width: 6rem;
height: 3rem;
line-height: 3rem;
font-size: 1.2rem;
display: inline-block;
background: #06c;
color: #fff;
border-radius: .5rem;
text-decoration: none;
text-align: center;
}

通过设置根元素html的font-size字体大小,其他元素的大小使用rem来设置。
当屏幕改变时,只需改变html的font-size字体大小,其他元素的大小也会跟着相应改变,而无需再重新设置大小。
这种布局优点:
用在适配不同尺寸屏幕时,css中使用rem作为单位,代码就只需要写一遍。
不管在任何分辨率下,页面的排版都是按照等比例进行切换,并且布局没有乱。我只是通过一段js根据浏览器当前的分辨率改变font-size的值,就简单的实现了上面的效果,页面的所有元素都不需要进行任何改变。

通过JS去动态计算根元素的font-size,作用:所有设备分辨率都能兼容适配。
js代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
(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);

不用JS我们也可以做适配,一般我们在做web app都会先统计自己网站有哪些主流的屏幕设备,然后去针对那些设备去做media query设置也可以实现适配,例如下面这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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;
}
}

终端交互优化

Tap基础事件

移动web页面上的click事件响应都要延迟300ms

由来
ios safari双击放大页面,由于浏览器大都具备这种特性,所以浏览器都约定在300毫秒的间隔来判断是否是双击还是单击,超过300毫秒还没第二次点击浏览器才判断此次点击是单击。
本意是好的,正常的逻辑实现,但是在现实的应用场景中,用户往往会觉得 web app 的事件触发不是那么灵敏,有那么一点延迟。
参考阅读:5步解决移动设备上的300ms点击延迟

300ms延迟怎么破?使用Tap事件代替click事件

自定义Tap事件原理:

在touchstart、touchend时记录时间、手指位置,在touchend时进行比较,如果手指位置为同一位置(或允许移动一个非常小的位移值)且时间间隔较短(一般为200ms),且过程中未曾触发touchmove,即可认为触发了手持设备上的”click”,一般称它为”tap”

移动端click事件响应慢ms,所以用tap事件替换click事件,tap事件可通过touchstart与touchend自定义,也可以使用zepto.js实现.但是tap事件有bug(tap透传),触发之后过300ms后又触发click事件

Tap“点透(穿透)”的bug

即点击会触发非当前层的点击事件。
2
产生穿透事件的条件
1、两个dom在屏幕的垂直方向是重叠的,并且z-index不同。
2、采用touch系列的点击事件去点击朝外的dom,并且这个dom隐藏或者移开。
3、在下方的dom绑定了click或者默认的点击事件(a标签,buttom等)
只有满足上述条件才会触发穿透事件,就是点击外dom,外dom消失,但下边的dom也会触发click事件(比如跳转链接)
产生此现象的原因:
因为click的300延迟,导致用户体验不佳,所以很多人都会采用touch系列代替click。
在点击事件中,点击的顺序是这样的:
touchstart > touchmove > touchend > click
而轮到click事件的时候还在再延迟了300毫秒,所以touchstart的触发速度是远大于click的,回到上述的产生穿透的条件中去
1、touchstart事件触发,外层dom消失,可是点击屏幕后会有个浏览器默认的click产生,首先就作用于当时click触发时点击的屏幕最外层的dom,即在重叠的条件下,zindex最大的dom,然后顺着dom树往上爬
2、因为有300毫秒的延迟,所以在第一步的touchstart后,外层dom就消失了,等300毫秒后click触发了,等着他的dom却是在下面那层的dom(因为此时这个dom已经在最上层了),所以原本在下面的这个dom就触发了click事件。
所以说外层dom会消失是很重要的条件,如果外层dom没有消失,那延迟的click触发时还是作用在外层的dom上,而外层dom没绑定click事件。
这就是穿透的原理。

Tap透传的解决方案
1.使用缓动动画,过渡300ms的延迟
2.中检测dom元素的加入,让中间层接受这个”穿透”事件,稍后隐藏
3.”上下”都使用tap事件,原理上解决tap透传事件(但不可避免原生标签的click事件)
4.取消click默认事件。
既然每次单击是都会有个浏览器的click默认事件触发,既然我们不需要,那就把这个默认事件取消掉就好了,所以在js中加上这句话

1
2
3
if (ev.type == 'touchend') {
ev.preventDefault();
}

5.改用Fastclick库

触摸touch

touch事件touch是针对触屏手机上的触摸事件。现今大多数触屏手机webkit内核提供了touch事件的监听,让开发者可以获取用户触摸屏幕时的一些信息。
其中包括:touchstart,touchmove,touchend,touchcancel 这四个事件.touchstart,touchmove,touchend事件可以类比于mousedown,mouseover
,mouseup的触发。

触摸touch常见事件及属性
  • touchstart : 当手指触摸到屏幕会触发(已经有手指放屏幕上不会触发)
  • touchmove : 当手指在屏幕上移动时,会连续触发;
  • touchend : 当手指离开屏幕时,会触发;
  • touchcancel:系统取消touch时触发(不常用)

除了常见的事件属性外,触摸事件包含专有的触摸属性:

  • touches:跟踪触摸操作的touch对象数组
  • targetTouches:特定事件目标的touch对象数组
  • changeTouches:上次触摸改变的touch对象数组
    每个touch对象包含属性:
  • clientX:触摸目标在视口中的X坐标。
  • clientY:触摸目标在视口中的Y坐标。
  • identifier:标识触摸的唯一ID。
  • pageX:触摸目标在页面中的x坐标(包含滚动)
  • pageY:触摸目标在页面中的y坐标(包含滚动)
  • screenX:触摸目标在屏幕中的x坐标。
  • screenY:触摸目标在屏幕中的y坐标。
  • target:触摸的DOM节点目标。

3

弹性滚动(IOS系统适用)

当客户端的页面滚动到顶部或底部的时候,滚动条会收缩并让我们多滑动一定距离,通过缓冲反弹的效果,带给用户良好的体验。

移动web页面也有这样的效果,但滚动有几种情况需要考虑:

  • body层滚动:(系统特殊化处理)
    自带弹性滚动,overflow:hidden会失效,GIF和定时器暂停。
  • 局部滚动:
    没有弹性滚动,没有滚动惯性,不流畅
    局部滚动开启弹性滚动:
    1
    2
    3
    4
    body{
    overflow:scroll;
    -webkit-overflow-scrolling:touch;
    }

Android不支持原生的弹性滚动!需要借助第三方库iScroll来实现。

下拉刷新

顶端下拉一小点距离,页面弹性滚动向下

上拉加载

使用scroll事件,而不是touch事件(android有bug)

Web App打包工具:

基于HTML5+CSS3+JS开发Web App,通过打包工具将Web App变成ISO/Anroid应用。
常见的打包工具:

  • Appcan
  • phonegap
  • appcelector
  • Intel XDK(设计开发打包一体化工具)

常见Web App框架

3.1
3.2

Web APP优缺点:
致命缺陷:运行效率太差
纯Web App应用参考:”豆瓣音乐人”

Hybrid App:

如桌面平台上的Hybrid App应用:酷我音乐盒/QQ
移动平台上的Hybrid App:如QQ
3.3
3.4
Hybrid App优缺点

  • 综合了开发效率和运行效率
  • 发版本方便
  • 运行效率中等(切换engine交互效果)
  • 需要写一点原生代码(至少2个平台)

参考链接:

  1. click300延迟与点击穿透
  2. web app变革之rem http://isux.tencent.com/web-app-rem.html
  3. 用rem来做响应式开发 http://520ued.com/article/53e98eafbb16a74c41b5de77
坚持原创技术分享,您的支持将鼓励我继续创作!