[关闭]
@fengfeng 2014-10-24T06:46:24.000000Z 字数 11975 阅读 2361

mobile page note

note mobile


position:fixed

Position fixed & scrolling on iOS
应该是反映最多的问题.但是手机屏幕很小,对于一些要重点突出的地方,还特别需要fixed在视口的某个位置,

我遇到的问题包括:

呼出系统输入法后,fixed元素位置乱飘.

当文本框获取焦点的时候,就把元素设置为position: static; 失去焦点后再设置为fixed。

fixed的元素是后弹出的,点击发生击穿现象(会触发弹层下面元素的click)

涉及整页动画时,元素位置乱飘 如果祖先元素使用了transform相关的样式,fixed元素的不按照视口来定位.

fixed的元素有input框时在ios上的bug(可以考虑头和底部定高,中间加上一个iScroll的内容区域实现头尾固定,中间内容滑动的UI交互布局);

解决的思路

用代码,触发一下滚动(document.body.scrollTop =
xx),我用这个方法解决了iPhone某版本上(specifically Webkit 534.46 on iOS 5.1.1 as mobile Safari, and now Chrome for iOS),弹层击穿现象.如果测试的时候,出现fixed相关问题,都可以先试着手动滚动一下屏幕,看能否修复.或添加 cursor:pointer样式
用absolute元素替换.基本能解决问题,但是要多些一些代码,而且有明显的卡顿感.

现在的情况

现在的情况是,新版的手机浏览器处理fixed元素的健壮性越来越好.呼出输入法虽然还有些bug,但是比以前出现的问题要好很多,一般可以接受.除了第四条,其他问题基本都还ok.

关于第四条,把fixed元素移出去就好.如果你再body上应用transform,那么请容许我给你点根蜡烛.stackoverflow上有个相关的问题,大家可以看一下.

补充说明

有一个全屏遮罩的fixed写法,一直再用

.full-cover{
position:fixed;
top:0;left:0;right:0;bottom:0;
}
这个用过bootstrap的有心人应该都知道.但是还是遇到不少不知道的同学,在这啰嗦一下.

tap 穿透问题

tap事件穿透(解决方案:click事件代替, 或者尝试fastclick这个框架);
或者尝试下面的办法重写一下zepto绑定的事件

/*************** 重写zepto on方法避免事件穿透 ******************/
    (function() {
        var INTERVAL_MIN = 500;
        var lastCalledTime = (new Date()).getTime();
        function throttle(handler) {
            return function() {
                var curTime = (new Date()).getTime();
                //两次tap事件的间隔如果不大于500
                if(curTime - lastCalledTime > INTERVAL_MIN) {
                    lastCalledTime = curTime;
                    handler.apply(this, arguments);
                }
            }
        }
        var oldOn = $.fn.on;
        $.fn.on = function( evt ){
            if(evt === 'tap'){
                var args = Array.prototype.slice.call(arguments);
                var handlerIndex;
                for(var i = 0; i < args.length; i++) {
                    if(typeof args[i] === 'function') {
                        handlerIndex = i;
                        break;
                    }
                }
                args[handlerIndex] = throttle(args[handlerIndex]);
                this.on('click', function(e) {
                    e.preventDefault();
                });
                return oldOn.apply( this, args );
            }
            return oldOn.apply( this, arguments );
        };
    })();

解决原理:正常有意义的用户操作不会在500毫秒内连续触发两次tap事件,如果发现两次tap事件的时间间隔不大于500毫秒则阻止第二次tap事件
有两个副作用和一个不能修复的问题
(1). 可能会穿透点到a链接上,需要额外给a绑定tap事件,在js中进行跳转
(2). trigger主动触发得时候可能有问题
(3).无法解决跨页面的穿透问题

链接的打电话和发短信功能

通过设置a标签的href 为tel:电话号码和sms:电话号码,可以直接使用手机的打电话和发短信功能.但是这里有两个小坑.

1.安卓某些版本的webview上,tel:会报找不到页面

解决方案 修改java代码

2.发短信时,如果有预加内容,安卓和iPhone的schema时不同的,需要区别对待,主要?和;

安卓: <a href="sms:123456789?body=sometext">点击发短信</a>
//ios7下sms的body处好像有问题,无法预制发送内容.
ios:<a href="sms:123456789;body=sometext">点击发短信</a>

touch

1.安卓下swipe*的方法很难触发

这是安卓的一个老问题了.谷歌一下 类似zepto android swipe的关键字,就能发现不少.很多项目中的issue都能找到这个问题,连安卓自身项目里都有相关issue(链接要翻墙)

解决方法就是在touchstart或touchmove事件中,主动调用e.preventDefault()

如果使用zepto的库,有两种方案,

//1.在监听函数中调用e.preventDefault()

$('#ele_id').on('swipeLeft',function(e){
    e.preventDefault();
    //....
})

//2.修改库的源代码,再bind touchmove事件时,添加

.on('touchmove MSPointerMove pointermove', function(e){
            if((_isPointerType = isPointerEventType(e, 'move')) &&
                !isPrimaryTouch(e)) return
            firstTouch = _isPointerType ? e : e.touches[0]
            cancelLongTap()
            touch.x2 = firstTouch.pageX
            touch.y2 = firstTouch.pageY

            deltaX += Math.abs(touch.x1 - touch.x2)
            deltaY += Math.abs(touch.y1 - touch.y2)

            //只有下面两行是要修改的代码,上面的代码帮大家定位
            //这里当时安卓系统,且是明显的横向滑动时,调用preventDefault
            if(isAndroid && deltaX > 10 && deltaX>deltaY){
                e.preventDefault()
            }
})

(注:`isAndroid`变量是用来表征是不是安卓手机

var isAndroid = false;
if (navigator.userAgent.match(/Android/i)){
    isAndroid =true;
}

)//end of 注

对于安卓的swipeUp和swipeDown,就不建议去做任何干涉,因为会影响浏览器本身的滚动

2.以上下滑动为主的操作,有可能触发swipeLeft/Right事件,而不是swipeUp/Down事件.这个主要是因为native scroll的一些特性,导致算距离时竖向的距离可能会很小,而上下滑的最后,一般会有一个横向滑动的连带动作,导致deltaX>deltaY,从而判断出错.

zepto中,delta在touchmove中是累加的,所以基本没啥问题.

deltaX += Math.abs(touch.x1 - touch.x2)

af.touchEvents.js中,问题很严重.我是把取坐标时的pageX/pageY改成了clientX/clientY来解决这个问题的.供大家参考

补充说明

最后说一下,还是慎用左右滑动的设计,一是兼容性问题.二是,微信等app是手机网页主要的入口,而从左向右的滑动,很容易关闭页面.

audio

看国外的资料,因为MP3的版权问题,会让大家准备ogg等格式的文件.在天朝,版权问题吗(省略几个字)…所以直接上MP3.

<audio>
    <source id="mp3source" src="yours.mp3" type="audio/mpeg">
</audio>

虽然很多资料上说,MP3格式的兼容性最好.但是这里还是有坑.当时运营同学给我一段音频,mp3格式,发现iPhone下放不了.查了很多资料,最后在一个论坛里找到,ios下MP3要满足一定条件

Try changing the MP3 to 44100Hz, 128kbs
其他参数的我没试过,但是按上面要求转换出得MP3,都可以在iPhone上使用.

移动端 HTML5 audio autoplay 失效问题

这个不是 BUG,由于自动播放网页中的音频或视频,会给用户带来一些困扰或者不必要的流量消耗,所以苹果系统和安卓系统通常都会禁止自动播放和使用 JS 的触发播放,必须由用户来触发才可以播放。

解决方法思路:先通过用户 touchstart 触碰,触发播放并暂停(音频开始加载,后面用 JS 再操作就没问题了)。

解决代码:

document.addEventListener('touchstart', function () {
document.getElementsByTagName('audio')[0].play();
document.getElementsByTagName('audio')[0].pause();
});
方案出处:http://stackoverflow.com/questions/17350924/iphone-html5-audio-tag-not-working

扩展阅读:http://yujiangshui.com/recent-projects-review/#toc-7

离线功能

离线缓存更新成功后必须刷新页面才能显示新的修改(写个全局的方法,监听updateready后,主动帮用户刷新一次页面);

localStorage/sessionStorage

PC端,这两个API在低版本的IE下是没有,所以是需要用try..catch包裹的.

在移动端,我刚刚开始是不加的,所测试的手机也没问题.但是现在很多浏览器有无痕模式,这个模式下,localStorage相关的API时禁用的.所以使用时,还是要保证代码的健壮性

input

input type date 的 placeholder

支持性有一定问题,因为浏览器会针对此类型 input 增加 datepicker 模块,看上去没那么必要支持 placeholder。

对 input type date 使用 placeholder 的目的是为了让用户更准确的输入日期格式,iOS 上会有 datepicker 不会显示 placeholder 文字,但是为了统一表单外观,往往需要显示。Android 部分机型没有 datepicker 也不会显示 placeholder 文字。

简单的进行了测试:

桌面端(Mac)

Safari 不支持 datepicker,placeholder 正常显示。
Firefox 不支持 datepicker,placeholder 正常显示。
Chrome 支持 datepicker,显示 年、月、日 格式,忽略 placeholder。
移动端

iPhone5 iOS7 有 datepicker 功能,但是不显示 placeholder。
Andorid 4.0.4 无 datepicker 功能,不显示 placeholder
问题解决方法:

先使其 type 为 text,此时支持 placeholder,当触摸或者聚焦的时候,使用 JS 切换使其触发 datepicker 功能。


方案出处:http://stackoverflow.com/questions/20321202/not-showing-place-holder-for-input-type-date-field-ios-phonegap-app

oveflow

伪类 :active 生效

要CSS伪类 :active 生效,只需要给 document 绑定 touchstart 或 touchend 事件

<style>
a {
  color: #000;
}
a:active {
  color: #fff;
}
</style>
<a herf=foo >bar</a>
<script>
  document.addEventListener('touchstart',function(){},false);
</script>

消除 transition 闪屏

-webkit-transform-style: preserve-3d;
/*设置内嵌的元素在 3D 空间如何呈现:保留 3D*/
-webkit-backface-visibility: hidden;
/*(设置进行转换的元素的背面在面对用户时是否可见:隐藏)*/

关于 iOS 与 OS X 端字体的优化(横竖屏会出现字体加粗不一致等)

iOS 浏览器横屏时会重置字体大小,设置 text-size-adjust 为 none 可以解决 iOS 上的问题,但桌面版 Safari 的字体缩放功能会失效,因此最佳方案是将 text-size-adjust 为 100% 。

-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
text-size-adjust: 100%;

JS 事件相关

click 事件普遍 300ms 的延迟 在手机上绑定 click 事件,会使得操作有 300ms 的延迟,体验并不是很好。 开发者大多数会使用封装的 tap 事件来代替 click 事件,所谓的 tap 事件由 touchstart 事件 + touchmove 判断 + touchend 事件封装组成

iOS 点击会慢 300ms 问题

https://developers.google.com/mobile/articles/fast_buttons?hl=de-DE http://stackoverflow.com/questions/12238587/eliminate-300ms-delay-on-click-events-in-mobile-safari

使用 CSS3 动画的时尽量利用3D加速,从而使得动画变得流畅。动画过程中的动画闪白可以通过 backface-visibility 隐藏。

-webkit-transform-style: preserve-3d;
-webkit-backface-visibility: hidden;

禁止 iOS 弹出各种操作窗口

-webkit-touch-callout:none

不让 Android 手机识别邮箱

<meta content="email=no" name="format-detection" />

禁止用户选中文字

-webkit-user-select:none

动画效果中,使用 translate 比使用定位性能高

http://paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/

获取滚动条

window.scrollY
window.scrollX
比如要绑定一个 touchmove 的事件,正常的情况下类似这样(来自呼吸二氧化碳)

$('div').on('touchmove', function(){
//.….code
});
而如果中间的 code 需要处理的东西多的话,FPS 就会下降影响程序顺滑度,而如果改成这样

$('div').on('touchmove', function(){
setTimeout(function(){
//.….code
},0);
});
把代码放在 setTimeout 中,会发现程序变快.

JS 动态生成的 select 下拉菜单在 Android2.x 版本的默认浏览器里不起作用

解决方法删除了 overflow-x:hidden; 然后在JS生成下来菜单之后 focus 聚焦,这两步操作之后解决了问题。(来自岛都-小Qi)

参考:http://stackoverflow.com/questions/4697908/html-select-control-disabled-in-android-webview-in-emulator

xx浏览器

关于 iOS 系统中,WebAPP 启动图片在不同设备上的适应性设置

http://stackoverflow.com/questions/4687698/mulitple-apple-touch-startup-image-resolutions-for-ios-web-app-esp-for-ipad/10011893#10011893

关于 iOS 系统中,中文输入法输入英文时,字母之间可能会出现一个六分之一空格(焦点科技葛亮)

可以通过正则去掉

this.value = this.value.replace(/\u2006/g, '');

三星I9100 (Android 4.0.4)不支持display:-webkit-flex这种写法的弹性布局,

但支持display:-webkit-box这种写法的布局,

相关的属性也要相应修改,如-webkit-box-pack: center;

移动端采用弹性布局时,建议直接写display:-webkit-box系列的布局

touchmove事件在Android部分机型(如LG Nexus 5 android4.4,小米2 android 4.1.1)上只会触发一次

解决方案是在触发函数里面加上e.preventDefault(); 记得将e也传进去。

iOS 5.0- 的Date构造函数不支持规范标准中定义的YYYY-MM-DD格式,如 new Date('2013-11-11') 是 Invalid Date, 但支持YYYY/MM/DD格式,可用 new Date('2013/11/11')

IOS(7.1.1版本)使用webapp模式时滚动元素无法滚动到头,解决办法是设置 让APP占用整个屏幕空间布局。参考官方文档

IOS(7.1.1版本)滚动元素中设定其中某个元素的 innerHTML 属性一定机率导致画面闪动(估计是触发了重绘),解决办法是设置文字时使用textContent属性。

IOS(7.1.1版本)动态改变滚动元素中某个元素 top 属性一定机率导致画面闪动,解决办法是使用 translateY 替代

IOS(7.1.1版本)通过-webkit-overflow-scrolling: touch方式设定的滚动元素时,如果滚到头的时候拖动,会出现页面的整体滚动,解决办法见https://github.com/chemzqm/scrollfix/blob/master/index.js

其他

有些比较老旧的手机不支持多个触点,可能是硬件不支持,也可能是软件问题。这并不是微信的坑,对于这个问题其实我是早就遇到过的,心里有底,也就不算问题了。

上传图片

  1. 手机上传图片会变横,比如:竖着拍照上传,图片不是竖的,而变成横的。这个也不是微信的问题,是因为我以前还没在手机上做过图片上传,所以第一次遇见。

解决方案:解析图片的EXIF信息,使用其中的orientation字段,根据方向调整图片。参考:https://www.imququ.com/post/how-to-auto-rotate-photo-in-js.html

2、 手机上传图片会变横,比如:竖着拍照上传,图片不是竖的,而变成横的。这个也不是微信的问题,是因为我以前还没在手机上做过图片上传,所以第一次遇见。

解决方案:解析图片的EXIF信息,使用其中的orientation字段,根据方向调整图片。参考:https://www.imququ.com/post/how-to-auto-rotate-photo-in-js.html

3、 Android版微信上传图片不支持拍照,只能从图库中选择,参考:http://mp.weixin.qq.com/qa/index.php?qa=12686&qa_1=%E5%AE%89%E5%8D%93%E7%89%88%E5%BE%AE%E4%BF%A1%E5%86%85%E5%B5%8C%E6%B5%8F%E8%A7%88%E5%99%A8%E5%93%8D%E5%BA%94input-file%E4%B8%8A%E4%BC%A0%E6%96%87%E4%BB%B6%E4%B8%8D%E8%83%BD%E7%9B%B4%E6%8E%A5%E8%B0%83%E7%94%A8%E6%8B%8D%E7%85%A7%E6%88%96%E5%BD%95%E5%83%8F%E5%8A%9F%E8%83%BD-%E8%80%8Ciphone%E7%89%88%E6%89%8B%E6%9C%BA-%E6%98%AF%E5%8F%AF%E4%BB%A5%E7%9A%84

4、 一些Android手机,比如三星Note3,从SD卡中选择图片上传,会提示“请选择SD卡中的图片”。我理解这个SD卡是指外接SD卡,直接从手机内置存储中选择图片是可以上传成功。

5、 Android4.4下由于系统WebView的openFileChooser接口更改,导致无法选择文件,从而导致无法上传文件。现在,大多数浏览器都修复了此BUG,但当前版本5.3的微信内置WebView并未修复。参考:https://code.google.com/p/android/issues/detail?id=62220

目前Android4.4版本系统占比上升非常快,从目前监控数据来看,1个月内上升了2%,当前Android4.4总占比超过5%,希望微信能尽快修复此BUG。

目前最新进展:Android 4.4.3+ 以上的版本已经修复了这个BUG。

微信 本地存储

通过后期和同僚交流,得知微信不会主动清空缓存。可能是因为Android设置setDomStorageEnabled开启缓存,但没有设置存储目录,导致缓存被存储到临时目录中,临时目录就有被自动清除的可能。参考:http://stackoverflow.com/questions/2961460/my-android-html-application-is-losing-values-stored-in-localstorage-when-it-shut/5418555

可以确认cookie不会被主动清除。如果将微信进程杀死,过期时间为session状态的cookie会被清除。如果用户主动退出微信登入,所有cookie都会被清除。

得到一些新的反馈:1、有小部分安卓机器cookie/localstorage都失效,目前微信那边没有好的解决方案;2、一般来说cookie + localstorage就能解决大部分问题。我现在使用了cookie + localstorage双备份的策略。

在微信下,一切本地存储的方式都是不靠谱的,唯一靠谱的是微信开发API,使用微信的用户OpenID来跟踪用户。

iscroll

1】. 动态加载某个模块,发现iscroll 没有 效果。

【2】. 使用jquery 的 (slideDown、slideUp )动画效果,发现iscroll的滚动条算高度会有问题。

【1】【2】的 解决方案:setTimeOut(function(){ new IScroll("#wrapper") },100);

【3】:iscroll里面的a链接点击没有效果。

解决方案:找到 preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|A|IMG)$/ } 这句话,去掉 |A,就可以了,因为默认禁用了。

【4】:使用iscroll拖动到顶部,加载下一页数据。(此部分完全可以抽出来,做成一个通用的分页,偸了个懒)

tap 点透 问题】------------------------

起因:由于我给页面大量用了 tap, 解决了click点击的延迟问题,同时也带来了新的问题。

如果我给document绑定tap事件,如果,弹层模板下面,有个元素也绑定了,此时就会出现点透的问题。

tap的 ”点透“ 问题。

推荐 大家可以看看 , 叶小钗 关于 “点透” 问题的文章分析:http://www.cnblogs.com/yexiaochai/p/3442220.html

解决方案:fastclick , 确实是解决了这个问题。

解决方案地址:http://blog.youyo.name/archives/zepto-tap-click-through-research.html

Viewport

小屏幕显示大网页
缩放
480px屏幕显示320px网页
布局中的pixel ≠ 屏幕上的pixel
高分辨率图片的使用
为什么iPhone4上看是模糊的?不是说iPhone4屏幕效果更好吗?

touch 不等于 mouse

移动设备上通常用touch事件而非mouse事件
WP没有touch,还是用mouse
touchstart -> touchend的过程通常比click事件更灵敏
可以用这个特点来自己制作快速点击的事件
iOS较新版本支持很多点,而Android直到2.3还是只支持一个点
双指缩放图片

抓狂的onscroll

大多数手机和浏览器都有惯性滑动
惯性滚动停止以后才触发onscroll事件
有的手机和有的UCWeb下面是以抽筋一样的频率触发
scroll周边问题
有的浏览器下取窗口滚动位置不准确

position:fixed

不支持
iOS 5支持
诡异的1px来回抖动
Android 2.3支持
版本和第三方定制差异,可用性较低

window.innerHeight

iOS下OK
Android下弹出虚拟键盘时常会造成悲剧
使用一个height:100%的绝对定位div来取高度

translate3d

硬件加速?忽悠?
Android有时候会和rotate冲突
这种时候即使用TransformMatrix都不给力
性能!性能!性能!
卡:少用特效
虚:参考“卡”,碰运气
闪:-webkit-backface-visibility:hidden; -webkit-perspective:1000;

软键盘

在软件盘弹出之后,如果想点击一个按钮又不希望软键盘收起,可以在touch事件中调用e.preventDefault()防止软键盘被收起。这个例子可参见百度移动搜索首页的文本框,输入内容之后,点击右侧的“X”按钮清空输入,但软键盘不会收起。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注