今天一位同事問我關于本文標題描述的功能如何實現,Jerry在網上隨便搜了一下,類似的例子非常多,這里隨便找了一個例子做了精簡,方便Jerry以后重用。

其實之前Jerry的文章 只要200行JAVAScript代碼,就能把特斯拉汽車帶到您身邊,里面使用到的React-Native加上ViroReact的組合,也能實現用JavaScript調用手機攝像頭并拍照的功能,不過那個應用是通過React-Native打包生成的原生應用,和本文介紹的例子稍有不同。這篇文章給出的例子是一個運行在瀏覽器里的純web應用。
先看效果。我已經把這個web應用通過github gh-pages的方式托管到了我在github的個人博客上,通過以下鏈接訪問:https://jerrywang-sap.cn/FioriODataTestTool2014/WebContent/099_camera.html
我首先通過筆記本電腦訪問,瀏覽器會彈出窗口詢問用戶是否允許該應用訪問設備上的攝像頭:

點擊允許之后,應用下方區域就會實時顯示我的攝像頭正對著的區域的圖像:

點擊“拍照”按鈕后,攝像頭顯示的圖像就會被固化在該按鈕下方,并且以圖片的方式自動保存到本地。

在我的三星手機上訪問該鏈接,首先一樣要授權該應用使用攝像頭:

對準我公司工位上吳脊老師送我的這個吉祥物,一只種類為哨兵的異形,點擊拍照按鈕:

自動生成一張圖片并保存到手機上:


我的源代碼位置(注意是gh-pages分支):https://github.com/i042416/FioriODataTestTool2014/tree/gh-pages/WebContent/camera

幾個關鍵的代碼點
(1) JavaScript之所以通過瀏覽器能夠識別到設備可用攝像頭(包括可用的音頻輸入和輸出設備),是因為現代瀏覽器支持的一組名為WebRTC(Web Real Time Communication,網頁即時通信)的API. 這個API能幫助Web應用開發人員通過簡單的JavaScript編程就能實現功能豐富的實時多媒體應用,而無需學習多媒體的數字信號處理知識。Web應用的使用者也無需下載額外的插件。
具體到Jerry例子里的代碼,用JavaScript進行設備可用多媒體設備的檢測,一行代碼調用就能搞定:
navigator.mediaDevices.enumerateDevices().then(gotDevices).catch(handleError);

這句代碼前半段navigator.mediaDevices.enumerateDevices()是瀏覽器支持的原生API,這是一個異步調用,返回一個promise對象:

等到該異步調用的結果可供應用程序使用之后,我們通過鏈式調用then傳入的回調函數gotDevices被觸發,輸入的參數就是navigator.mediaDevices.enumerateDevices()調用的返回值。在調試器里看看這個返回值的明細:

從調試器里得知enumerateDevices這個函數返回了我筆記本電腦上一系列可用的音視頻設備,這些信息和我通過操作系統里看到的設備信息一致:

(2) 我的html頁面里定義了一個HTML5原生支持的video標簽, 用于顯示通過設備攝像頭觀察到的圖像。

但是我們還需要把設備攝像頭同這個video標簽關聯起來。方式是給這個標簽的dom對象的srcObject屬性賦一個MediaStream(媒體數據流)對象。

這個MediaStream對象從哪里來?同理,通過鏈式調用navigator.mediaDevices.getUserMedia(constraints)得到:

(3) 點擊拍照按鈕后,自動生成圖片并下載到本地的功能在按鈕的click事件響應函數里實現。首先調用canvas標簽對應Context的API drawImage將顯示攝像頭內容的video標簽當前顯示的內容繪制到canvas標簽頁上,然后用此內容生成格式為jpeg的圖片,下載到本地。

明天Jerry會繼續分析SAP云平臺相關的內容,敬請期待。