HTML5,JavaScript与现代浏览器三驾马车的结合,使得传统Web应用能够实现比过去更多更丰富的用户体验交互功能。摄像头现在已经成为智能手机的标配,前端Web应用也越来越需要打开本地摄像头、扫描条码、二维码。本文介绍两种在浏览器环境下通过JavaScript调用设备摄像头的开发技术。方法一:基于现代浏览器支持的WebRTCAPI实现我用这个思路实现了一个简单的网页,所有源代码都维护在如下Github代码仓库:https://github.com/wangzixi-d...首先看运行Web应用程序的效果。从笔记本电脑访问时,浏览器会弹出一个窗口询问用户是否允许该应用程序访问设备上的摄像头:点击允许后,应用程序下方的区域将显示我的相机所面对区域的图像实时:点击“拍照”按钮后,相机显示的图像会固化在按钮下,并自动保存为本地图片。要在我的三星手机上访问这个链接,首先要授权应用使用相机:拍下我电脑前的陌生人影:自动生成图片并保存在手机上:几个关键实现要点:(1)JavaScript之所以能够通过浏览器识别出设备可用的摄像头(包括可用的音频输入输出设备),是因为支持了一套叫做WebRTC(WebRealTimeCommunication,网页即时通信)的API由现代浏览器。该API可以帮助Web应用开发者通过简单的JavaScript编程实现功能丰富的实时多媒体应用,无需学习多媒体的数字信号处理知识。Web应用程序的用户不需要下载额外的插件。使用JavaScript检测设备可用的多媒体设备。核心代码如下:navigator.mediaDevices.enumerateDevices().then(gotDevices).catch(handleError);这段代码的前半部分navigator.mediaDevices.enumerateDevices()是nativeAPI,是一个异步调用,返回一个promise对象:当异步调用的结果对应用可用后,回调函数gotDevices通过然后触发链式调用,输入参数为navigator.mediaDevices.enumerateDevices()调用的返回值。查看调试器中返回值的详细信息:我从调试器中了解到,enumerateDevices函数返回了我笔记本电脑上一系列可用的音视频设备,这与我通过操作系统看到的设备信息是一致的:(2)我的html页面中定义了一个HTML5原生支持的video标签,用于显示通过设备摄像头观察到的图像。但是我们还需要将设备摄像头与视频标签相关联。方式是给这个标签的dom对象的srcObject属性赋值一个MediaStream(媒体数据流)对象。这个MediaStream对象来自哪里?同理,链式调用navigator.mediaDevices.getUserMedia(constraints)得到:(3)点击相机按钮后,在按钮的点击事件响应函数中实现自动生成图片并下载到本地的功能。首先调用canvas标签的Context对应的APIdrawImage在canvas标签页中绘制出显示摄像头内容的video标签当前显示的内容,然后使用该内容生成jpeg图片下载到本地。方法二:使用SAPUI5自定义控件这种方法本质上和方法是一样的,只是封装性更好。将方法1中描述的步骤封装成一个SAPUI5可重用控件,方便使用SAPUI5前端框架。开发的前端程序员直接使用。关于SAPUI5这个企业级前端开发框架的介绍,可以参考笔者之前的InfoQ文章:企业级前端应用开发框架UI5的发展历史介绍。先回顾一下方法一的技术实现要点:(1)在web应用的HTML页面中定义用于显示视频的HTML5原生标签:video(2)使用WebRTCAPI获取对应的MediaStream对象devicecamera,然后将这个对象的实例赋值给video标签对应的DOM对象的srcObject属性。以上两步实现后,我们通过摄像头观察到的视频图像就可以实时显示在web应用的video标签中。至于将某个时间点video标签中显示的视频内容保存为图片并下载,相应的javascript代码对于所有前端框架来说差别不大,本文略过。所以,使用SAPUI5开发,我们只需要重复以上两步即可。SAPUI5应用程序最常用的视图格式是XML视图。如果我们直接将HTML原生视频或div标签添加到XML视图中会发生什么?404错误,UI5框架无法加载div.js脚本文件。笔者还在SAP成都研究院CRMFiori应用开发团队工作时,曾写过一篇SAPUI5框架代码的学习教程。里面有两篇文章,详细介绍了SAPUI5XML视图运行时的渲染原理:为什么我的formatter不起作用?一个解决问题的例子,了解它是如何工作的我如何在给定的Fiori控件上自学-第10部分简单地说,SAPUI5中有一个XMLTemplateProcessor.js的实现,它在运行时充当XML视图的源文件之后被浏览器加载并解析成DOM,它会深度优先遍历DOM树,为它遇到的每一个UI5标签加载它的实现文件(如果是UI5调试模式),然后创建这个标签对应的实例。回到本文的例子,我写到SAPUI5XML视图中的div标签被认为是一个SAPUI5XML控件,所以UI5框架自动寻找不存在的div控件的实现文件,当然它找不到它。知道了问题出在哪里,自然就会有解决的办法。将HTML5原生标签video封装成一个UI5控件不就行了吗?SAPUI5开源社区中已经有打包好的库:https://github.com/tiagobalme...先看下这个例子在笔记本上访问的效果:点击显示在屏幕上的摄像头拍摄的内容页面,它会自动保存成图片。手机端显示效果:那么我们来看一下这个库的实现原理。相机自定义UI5控件的实现层次结果如下:SAPUI5自定义控件的实现包括三个JavaScript文件:library.js:定义控件的header级控件信息,如名称,版本号,和依赖关系。Camera.js:实现了将WebRTCAPI获取的MediaStream对象实例绑定到控件封装的video元素上的步骤。CameraRender.js:负责将此自定义控件的XML视图中的标签Camera渲染成原生video和canvas标签的组合。SAPUI5的每个控件都有对应的渲染类,用于完成XML视图中的UI5标签到HTML5原生标签的转换:这个自定义控件怎么用?在XML视图中使用如下定义即可:
