-
Notifications
You must be signed in to change notification settings - Fork 10
Description
这段时间做了几个用在微信上推广H5触屏的项目,由于之前做过手机股票行情,正好这段时间一直在总结以前的一些东西,结合做过得移动端的项目,把遇到的问题汇总一下。
首先也是最重要的手势:滑动。尽管移动端浏览器虽然没有直接提供滑动事件,但是提供了与滑动相关的事件(touch)来替代模拟,然而还是有些问题需要注意的:
- 首先Windows Phone不支持touch事件(之前测试的是window phone 7版本,由于手上没有window phone手机,新版本是否支持有机会还是测试一下);企图用Mouse事件来替代模拟也是有问题的,Window Phone如果通过mouse事件模拟滑动,不会触发任何mouse事件,而当点击时会依次触发:mousemove mouseover mouseenter mousedown mouseup。
- 之前在做手机股票行情的时候尝试过用CSS3提供的新特性:transition-property和transform来设置 滑动(touchmove) 过程中的效果,当时对比这两个样式发现,拖拽时如果通过设置这两个属性来实现移动不是太不流畅,尽管通过transform会相对好点,但是还是会有卡顿情况(不确定具体原因,或许和垃圾回收或者屏幕的刷新率有关吧,也有可能程序写的有问题,回头还需要深入研究一下)。为了避免滑动中的卡顿,暂时改用设置left/top值,这样效果会相对好点。但是这并不是说transition和transform不可用,之所以不用主要还是因为touchmove中不够流畅,如果说没有拖拽而只是单纯的动画展示,那无疑通过设置transition或transform会更好。看过一篇关于动画性能的文章,感觉很不错: 《Javascript高性能动画与页面渲染》
- 虽然通过上面方法能够实现滑动,但是如果滑动对象的宽度或者高度是通过精确的像素来定义,那么如果横屏或者旋转屏幕时,问题可能就出来了:宽度和高度变了。尽管安卓和ios可以通过监听orign的变化,window phone监听resize,来重新设置,但是这样处理未免太麻烦,而且还是有个问题:安卓的在切换屏幕(如横屏)时,无法正确的获取screen.width和screen.height,或许现在可以通过其他的方式获取横屏后的宽和高,但是可能兼容也有问题。所以解决这种问题的最终方式就是使用相对宽度或者高度,通过%来设置。
- 不管是手机端还是PC端,浏览器都带有滚动scroll功能,如果我们通过模拟滑动事件,可能就会和系统自带的scroll功能冲突,所以这方面要谨慎。如果所有的滑动(上下左右)全部通过JS来模拟,如何判断是上下还是左右呢?可以通过touchmove时第一次手指的位置和touchstart时手指的位置对比来处理(如大于45°就是垂直滑动,小于就是水平)。在做这次微信推广项目中遇到一个问题,由于起初初滑动是通过transform实现的,但是如果绑定的滑动对象中有一个子元素需要用到系统的默认滚动,当设置样式
overflow:auto时就会阻止父元素绑定的滑动事件,感觉很奇怪,到现在还没搞清为什么。如果滑动的对象里面某个子元素确实需要用到系统滚动scroll功能,需要单独对这个区域绑定事件防止冒泡,阻止在滚动时父元素的滑动行为的发生。
手机端和PC端容易混淆的问题:
- 鼠标对于PC来说很重要,但是触屏时代的移动设备没有鼠标,只有手指,虽然也支持click时间,但是却发现明显的延迟,可惜的是移动端并没有提供标准的tap点击事件,当点击屏幕时(不滑动),会先后触发 :touchstart,touchend事件,只能通过判断这两个事件手指触发点的x,y坐标的位移(假设位移在10px以内),来封装tap事件。
- 有时候为了方便,我们可能会单独通过触发touchstart或者touchend事件来模拟点击tap,然而在ios中safari浏览器却有一个bug:点击后touch事件没有被立刻释放或者回收。假设touchstart事件触发一个
loaction.href跳转,如果跳转到的目标页面在上一个页面的touch位置有个链接的话,那么系统会人为用户点击了这个链接。不过这个问题是不是bug其实也不好说明,我将这个问题提交给apple,但是一直没有得到解决,所以只能尽量避免了。 - 关于键盘事件,PC端是实体键盘,而手机触屏版一般都是虚拟键盘。尽管都有键盘的说法,但对于ios却不支持键盘事件,相反在触屏手机上一般支持input事件,为了兼容我们可以利用这个事件来替代键盘事件。但是由于input是非键盘事件,监听到回车keyCode(13),所以回车提交基本上只能通过添加form表单,设置action的值来模拟了。
关于头部定位问题:
如果页面中有一头部区域是固定不变的,可以通过CSS中position:fixed来实现,然而IOS5之前的版本是不支持fixed属性的。通过动态的变换scrollTop是一种兼容的方法(当然也可以通过合理的HTML结构避免使用这两种方法)。对于部分浏览器如海豚或者QQ浏览器,如果尝试设置scrollTop的时候,由于浏览器本身可能会把默认的地址输入栏计入到scrollTop中,所以如果当滚动到一定高度对某个区域进行定位时,需要考虑或者减掉这个非页面本身多余的高度。这个高度可以在页面加载后重设页面的位置scrollTo(0,1)后来获取。
图片问题:
在设计移动端页面的时候,最头疼的可能就是图片的大小了,为了兼容不同分辨率的手机,往往会带来很多问题。目前的经验主要是通过以下方式来处理的:
- 图片一定要大,至于多大就看需求了;
- 设置图片的相对宽度(高度自适应),或者相对高度(宽度自适应),来适应不同分辨率的移动设备。然而这并不适用于背景图片(css2:background-image)。CSS3中新增加了
background-size用来设置背景图片的大小,但是没有使用过,不确定能否解决背景图片宽高自使用的问题。
另外window Phone支持背景gif动画图,安卓和safari不支持。
离线存储:
之前在做手机行情时尝试使用离线存储,但是最终没采用。但是发现了一些问题:
- 离线存储并不是只需要设置一个面,其他页面都能访问,需要每个页面都要添加,同时本身添加manifest的页面会被存储的,针对这个问题会在下次访问的时候访问离线数据,而不请求服务器,从而导致无法记录PV UV(对于这个问题,可能用其他机制来解决,比如通过img.src来请求server这样可以记录LOG);
- 对于更新本地离线文件,如果资源文件在前端是分布式存储的话,可能会遇到个问题,当用户请求页面是,会对比manifest文件,如果发现manifest文件变化,就会更新离线文件,这个时候如果在更新的时候请求的是另一台尚未同步最新资源文件的服务器,那么这个用户永远不会更新资源文件了(当然这个也是可以解决的,可以在保证所有前端服务器的资源文件全部更新后,在更换manifest文件)。
另外HTML5还提供了本地存储解决方案,为了兼容可以结合localStorage,userData,cookie来实现本地存储。具体可参见我的一个开源项目:https://github.com/abcrun/Storage
结语:
CSS3丰富了Web页面的展示,尽管很多功能在PC端由于多浏览器的存在以及版本的问题,支持程度各异,但是幸运的是移动端大多采用Webkit内核,对CSS3新特性支持相对丰富很多,所以对于移动端应用,如果CSS3能实现的尽量通过CSS特性来实现。