移动端 HTML5 使用原生
此篇文章,主要是总结我在项目中遇到的一些坑,也为后面的小伙伴在使用 video 标签时,提供一些思路和方法。
在移动端售后项目中,我主要遇到两个问题:
提升网购用户体验,还是要聚焦在售后服务的环节上。所以此次售后体验的飞跃项目(从京东 app -我的-退换/售后进入)对 H5 页面进行了重构,对业务功能进行了升级。
其中一个升级模块就是在申请售后环节,在之前仅有拍照基础上,增加了音频和 小视频的功能,借此机会为用户提供更丰富的多媒体反馈功能。技术上采用的是 H5 + JDReact 结合的模式。用户在点击录视频 icon 会触发调用React原生应用录制小视频,后端同学采用轮询方式往 H5 页面动态添加 video 标签。之后用户可以马上点击刚刚录制的小视频播放观看。算是在申请时候为用户增加的一个更为直观反馈的功能,也便于京东客服的处理。
既然决定用 video 标签实现视频回显播放,那么先了解 video 标签都有哪些重要的属性。
属性名字 | 描述 |
---|---|
src | 视频媒体地址 |
autoplay | 自动播放。iOS 蜂窝网络和 safari 中不支持。WebView 中可单独配置开启。 安卓可能支持该属性 |
loop | 循环播放。iOS 支持,Android 可能支持 |
controls | 播放器控制条。iOS 和 Android 支持 |
width | 视频的宽。iOS 和 Android 都需要给出 |
height | 视频的高。iOS 和 Android 都需要给出 |
poster | 封面图片。iOS 支持,Android 不一定支持,而且各产商表现差异大 |
对于 width 和 height,比较流行的做法还是以 1px * 1px 的形式放在视觉边缘的位置。以此避免隐藏和设置 0 宽高的 video,使得视频处于未激活状态。另外 poster 封面的在各个平台的兼容性并不好,体验较差。所以我直接用 来做一个初始化展示的效果图。
这里有一个小技巧,对于宽高。初始设定,可以使用 1px * 2px。对于安卓手机全屏播放基本会初始竖屏播放,而不是先横屏播放,然后加载视频后得到视频宽高比后再切换成竖屏播放。
在打算使用 video 标签时,我专门去网上找了一些资料。这样可以在遇到兼容性的时候做到有备无患。
方法 | iOS | Android |
---|---|---|
play | 只是要播放视频,响应的是 video.play() 方法,并不代表已经开始播放 | 和 iOS 一样,仅是响应 video.play() 方法 |
durationchange | 会执行一次,一定会获取到视频的 duration | 可能会执行多次,只有最后一次才能获取到真实的 duration,前面的 duration 都是0;但低版本 Android 可能获取到的 duration 是 0 或 1 |
canplay | 可以认为是视频元素没有问题,可以运行,没有更多含义了,基本用不上 | 同 iOS |
canplaythrough | 会有明确的缓冲,表示可以流畅播放了 | 没有什么用,视频仍然会卡住,数据可能还没有开始加载 |
playing | 明确表示播放开始了 | 依然没有用,视频可能并没有开始播放 |
progress | 有明确的下载,可以获取到当前的 buffer,并且全部下载完毕后不在触发 | 不一定有明确的数据下载,并且全部下载完毕后依然继续触发 |
timeupdate | 会有明确的进度变化,可以获取到currentTime | 进度不一定变化,currentTime 可能总是 0,但是第一次有 currentTime 变化的timeupdate 事件一定代表了视频开始播放了 |
error | iOS 中会有明确的错误抛出 | Android 中某些浏览器会莫名其妙的抛出 error |
stalled | 网络状况不佳,导致视频下载中断 | 在没有 play 之前,也可能会抛出该事件 |
虽然 video 的方法有很多,但是兼容性还是比较头疼的。不过在项目我仅仅用到了 play,load 方法。下面说一下我遇到的问题吧。
在售后的项目中,因为需要支持 JDReact 原生应用提供多媒体功能。所以小视频只需要在京东 app 内 WebView 做适配就可以。第一个问题就出现了。后端将视频 video 标签动态添加到页面中后,iOS app 内点击播放。发现无法播放。而在安卓版的京东 app 内 x5 内核的浏览器是可以播放的。
mediaWrapper.delegate('.load-video .video-wrap','click',function(){ video.play(); video.addEventListener('ended',function(){ video.webkitExitFullscreen(); }); });
当然有小伙伴会表示,那不动态添加 video 标签,采用更换 src 的方式来回显用户录制的小视频。经过测试,依然无法播放。究其原因,video 标签和audio 标签不同于一般的 img 多媒体标签,更换 DOM 或者属性值就能使其激活生效。video 标签和 audio 标签本身具有了时间特性,因而采用了不同的模式。所以在播放视频之前,需要调用 video 的 load 方法来重新加载更新视频。
mediaWrapper.delegate('.load-video .video-wrap','click',function(){ if(videoIsPlay){ video.play(); return false; } video.load();//PAY ATTENTION! video.play(); video.addEventListener('ended',function(){ video.webkitExitFullscreen(); videoIsPlay = true; }); });
iPhone7 的京东 app 可以播放视频了。感觉革命已经成功。突然发现自己的 iPhone6s 依然不能播放,再点一次突然又可以播放了。这又是什么原因?
我们先看一下需要点两次效果图。
京东 app 采用的内嵌 UIWebView 内核浏览器,如果比较古老的话,会触发需要用户点两次 bug。load 方法和 play 方法在 iOS 上都是需要用户手动触发的。就算你在点击回调里写两次 load 方法或者 play 方法依然是没用的。不过可以有效利用移动端 click 事件的 300ms 延迟特点来解决两次点击播放问题。给 video 同时绑定两个事件 tap 和 click 事件,在 tap 事件和 click 都调用 load 方法。并且在 click 事件中调用 play 方法。这样就能完美解决该问题了。
mediaWrapper.delegate('.load-video .video-wrap','tap',function(){ var video = document.getElementById('my-video'); if(videoIsPlay){ return false; } video.load(); });
看一下修改后的效果图:
我的移动端的经验还不是很丰富,对于 video 标签,只能说里面水太深~。不过赶在618之前圆满的完成了售后客服的飞跃项目,获得不少成长,感谢并肩战斗的后端、设计、产品等同学,特别感谢封面设计:竹子。最后我们来整体看一下售后小视频的功能吧。
HTML5 Video Events and API
https://www.w3.org/2010/05/video/mediaevents.html
Exploring HTML 5’s Audio/Video Multimedia Support
http://www.devx.com/webdev/Article/43324
移动端 HTML5
http://zhaoda.net/2014/10/30/html5-video-optimization/