前言
做过H5调用手机相册或者拍照的同学可能深有体会,在不同型号手机和不同的浏览器上表现各有差异,实属头疼。由于手机自带浏览器或者第三方浏览器实在太多,结合最近正在做的项目用户群体P90在微信上,文本单从兼容微信浏览器方面进行实验分析。
差异表现
一般的,使用<input type="file" />
调用其手机的文件资源管理器,通过accept="image/*,video/*"
属性区分调用相册,相册中筛选文件类型,可以是图片具体的格式,或者是视频的具体格式。采用capture="camera"
属性唤起相机,而在唤起相机后,是进行拍照还是录像是由accept
决定。
然后,真的会如上标准定义操作我们的手机吗?答案是否定的,Android和IOS上的表现差异较大,下面分别分析一下它们的差异性。
accept在Android和IOS的表现
添加accept
属性,在IOS微信浏览器上,点击后,会弹窗原生选择,待用户下一步操作,如果accept
的属性值
- 仅有
image/xxx
-> 选项【照片图库】【拍照】,点击【拍照】-> 唤起相机,只能拍照,点击【照片图库】-> 打开相册,只能选择图片 - 仅有
video/xxx
-> 选项【照片图库】【录像】,点击【录像】-> 唤起相机,只能录像,点击【照片图库】-> 打开相册,只能选择视频 - 有
video/xxx,video/xxx
-> 选项【照片图库】【拍照或录像】,点击【录像】-> 唤起相机,能录像和拍照,点击【照片图库】-> 打开相册,能选择视频和图片
由此可知,IOS上的表现与属性值的预期一致。
在Android微信浏览器上,点击后,会弹出原生的选择弹框,确认用户下一步操作
接下来分别点击【拍摄】和【从相册选择】进行测试。 - accept="image/*" -> 唤起原生 【拍摄】 和 【从相册中选择】弹窗 -> 点击【拍摄】唤起相机-拍照功能,点击【从相册中选择】-只能选择图片,没有视频,安卓手机
- accept="image/,video/" -> 唤起原生 【拍摄】 和 【从相册中选择】弹窗 -> 点击【拍摄】唤起相机-拍照功能,点击【从相册中选择】-只能选择图片,没有视频,安卓手机
- accept="video/,image/" -> 唤起原生 【拍摄】 和 【从相册中选择】弹窗 -> 点击【拍摄】唤起相机-拍照功能,点击【从相册中选择】-只能选择视频,没有图片,安卓手机
- accept="video/*" -> 唤起原生 【拍摄】 和 【从相册中选择】弹窗 -> 点击【拍摄】唤起相机-摄像功能,点击【从相册中选择】-只能选择视频,没有图片,安卓手机
- accept="video/mp4,video/ogg,video/webm,video/mov" -> 唤起原生 【拍摄】 和 【从相册中选择】弹窗 -> 点击【拍摄】唤起相机-摄像功能,点击【从相册中选择】-只能选择视频和图片,安卓手机
- accept="image/jpg,image/jpeg,image/gif,image/png" -> 唤起原生 【拍摄】 和 【从相册中选择】弹窗 -> 点击【拍摄】唤起相机-拍照功能,点击【从相册中选择】-只能选择视频和图片,安卓手机
- accept="image/jpg,image/jpeg,image/gif,image/png,video/mp4,video/ogg,video/webm,video/mov" -> 唤起原生 【拍摄】 和 【从相册中选择】弹窗 -> 点击【拍摄】唤起相机-拍照功能,点击【从相册中选择】-可以选择视频和图片,安卓手机
- accept="image/*,video/mp4,video/ogg,video/webm,video/mov" -> 唤起原生 【拍摄】 和 【从相册中选择】弹窗 -> 点击【拍摄】唤起相机-拍照功能,点击【从相册中选择】-可以选择视频和图片,安卓手机
- accept="video/mp4,video/ogg,video/webm,video/mov,image/*" -> 唤起原生 【拍摄】 和 【从相册中选择】弹窗 -> 点击【拍摄】唤起相机-拍照功能,点击【从相册中选择】-可以选择视频和图片,安卓手机
有点乱,而且貌似不是严格遵循accept
属性值规律。为了方便查看和比对区别,梳理成表格的形式
accept | Android | IOS | ||
---|---|---|---|---|
原生【拍摄】 | 原生【从照片选择】 | 原生【拍照/录像】 | 原生【照片图库】 | |
"image/*" | 拍照 | 图片,没有视频 | 拍照 | 图片 |
"image/,video/" | 拍照 | 图片,没有视频 | 拍照,录像 | 图片,视频 |
"video/,image/" | 拍照 | 视频,没有图片 | 拍照,录像 | 图片,视频 |
"video/*" | 录像 | 视频,没有图片 | 录像 | 视频 |
"video/mp4,video/ogg,video/webm,video/mov" | 录像 | 视频,图片 | 录像 | 视频 |
"image/jpg,image/jpeg,image/gif,image/png" | 拍照 | 视频,图片 | 拍照 | 图片 |
"image/jpg,image/jpeg,image/gif,image/png,video/mp4,video/ogg,video/webm,video/mov" | 拍照 | 视频,图片 | 拍照,录像 | 图片,视频 |
"image/*,video/mp4,video/ogg,video/webm,video/mov" | 拍照 | 视频,图片 | 拍照,录像 | 图片,视频 |
"video/mp4,video/ogg,video/webm,video/mov,image/*" | 拍照 | 视频,图片 | 拍照,录像 | 图片,视频 |
从中我们可以尝试总结规律
accept="video/xxx"
,即仅有视频格式情况下,Android点击原生【拍摄】唤起相机是录像功能;accept="image/xxx[,video/xxx]"
,即仅有图片格式或者图片加视频格式情况下,Android点击原生【拍摄】唤起相机都是照相功能;Android点击原生【从照片选择】唤起相册,若要想只筛选视频,最好使用
accept="video/*"
,只筛选最好使用accept="image/*"
,而图片和视频同时共存,视频和图片格式最好写全或者accept="image/*,video/xxx"
;capture在Android和IOS的表现
<input type="file" />
在以上已有accept
属性下,加上capture
属性,点击后可直接唤起相机,相机分为拍照和录像两种模式,同样的,我们分别测试Android和IOS的微信浏览器上的结果如下
accept | Android【拍摄】 | IOS【拍摄】 |
---|---|---|
"image/*" | 拍照 | 拍照 |
"image/,video/" | 拍照 | 录像,拍照 |
"video/,image/" | 拍照 | 录像,拍照 |
"video/*" | 录像 | 录像 |
"video/mp4,video/ogg,video/webm,video/mov" | 录像 | 录像,拍照 |
"image/jpg,image/jpeg,image/gif,image/png" | 拍照 | 录像,拍照 |
"image/jpg,image/jpeg,image/gif,image/png,video/mp4,video/ogg,video/webm,video/mov" | 拍照 | 录像,拍照 |
"image/*,video/mp4,video/ogg,video/webm,video/mov" | 拍照 | 录像,拍照 |
"video/mp4,video/ogg,video/webm,video/mov,image/*" | 拍照 | 录像,拍照 |
可以发现,这里直接唤起拍摄和之前通过原生选项框中【拍摄】(Android)或者【录像】(IOS)的表现一致!
实现选择照片(图片&视频)及拍照&录像
综合上述实验可以发现,没有一种accept
和capture
的值的组合可以实现在Android中,既要在相册中可以选择图片和视频,又可以直接拍照和录像的情况。
这样可以多一个人为选择弹窗或者将拍摄视频拆分开,类似这样
点击照片图标,Android手机弹出原始选项框,可以【从相册选择】图片和视频,也可以【拍摄】图片,点击拍摄图标,单纯支持录像。
最终的思路是
在Android微信环境下,点击照片图标触发的input
的accept
值为video/mp4,video/ogg,video/webm,video/mov,image/*
使其后续【拍摄】唤起相机拍照,唤起相册可以选择图片和视频;点击拍摄图标触发的input
的accept
值为video/mp4,video/ogg,video/webm,video/mov
,使其唤起相机录像功能;
伪代码实现
<uploader :accept="accept" label="照片" icon="picture" />
<uploader :accept="captureAccept" capture="camera" label="照片" icon="camera" />
const videoAccept = 'video/mp4,video/ogg,video/webm,video/mov'
// 【照片】accept
const accept = `${videoAccept},image/*`
// 【拍摄】accept
const UA = window.navigator.userAgent
const isAndroid = /Android/i.test(UA)
const isWechat = /MicroMessenger/i.test(UA)
const { isAndroid, isWechat } = Terminal
const captureAccept = isAndroid && isWechat ? videoAccept : ${videoAccept},image/*`
完~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。