天天看點

AngularJS中使用HTML5攝像頭拍照

1. 項目背景

公司開發一個網站,在做使用者頭像修改的時候上司提到增加一個由攝像頭拍照實作修改頭像的功能。因為我們網站是基于html5進行開發,是以就直接采用h5來實作拍照。起初覺得這個功能很簡單,但是做的時候才發現并不是那麼簡單的。

AngularJS中使用HTML5攝像頭拍照

這是在angularjs中成功實作調用攝像頭拍照并截圖上傳的例圖:

AngularJS中使用HTML5攝像頭拍照
AngularJS中使用HTML5攝像頭拍照

2. 如何調用攝像頭

$scope.photoerr = false; 

$scope.photobtndiable = true; 

var mediastream = null,track = null; 

navigator.getmedia = (navigator.getusermedia || 

                      navigator.webkitgetusermedia || navigator.mozgetusermedia || 

                      navigator.msgetusermedia); 

        if (navigator.getmedia) { 

            navigator.getmedia( 

           { 

               video: true 

           }, 

           // successcallback 

           function (stream) { 

               var s = window.url.createobjecturl(stream); 

               var video = document.getelementbyid('video'); 

               video.src = window.url.createobjecturl(stream); 

               mediastream = stream; 

               track = stream.gettracks()[0]; 

               $scope.photobtndiable = false;               $scope.$apply(); 

           // errorcallback 

           function (err) { 

               $scope.errorphoto(); 

               console.log("the following error occured:" + err); 

           }); 

              } else { 

            $scope.errorphoto(); 

        } 

代碼解析:

navigator為浏覽器對象,包含浏覽器的資訊,這裡就是用這個對象打開攝像頭。$scope為andularjs文法。第一步聲明

navigator.getmedia來調用浏覽器不同的打開攝像頭函數,目前僅有getusermedia、webkitgetusermedia、

mozgetusermedia、msgetusermedia四種方式分别對應通用浏覽器、google浏覽器、火狐浏覽器和ie浏覽器,浏覽器會自動

判斷調用哪一個函數。第二步是調用打開浏覽器,包含三個參數,分别為需要使用的多媒體類型、擷取成功傳回的流資料處理函數以及操作失敗傳回錯誤消息處理函

數。其中,使用時不僅可以設定視訊還能設定使用麥克風,設定方式為:

      video: true, 

      audio: true 

調用成功即打開攝像頭後傳回視訊流資料,我們可以将流資料設定到video标簽在界面上實時顯示圖像。mediastream用來記錄擷取到的流資料,track在chrome浏覽器中用來跟蹤攝像頭狀态,這兩個變量都能用來關閉攝像頭。

3. 拍照

$scope.snap = function () { 

        var canvas = document.createelement('canvas'); 

            canvas.width = "400"; 

            canvas.height = "304"; 

            var ctx = canvas.getcontext('2d'); 

            ctx.drawimage(video, 0, 0, 400, 304); 

            $scope.closecamera(); 

            $uibmodalinstance.close(canvas.todataurl("image/png")); 

}; 

拍照時需要使用到canvas标簽,建立一個canvas标簽,設定我們需要拍照的尺寸大小,通過drawimage函數将video目前的圖像保

存到canvas标簽,最後将圖像資料轉換為base64資料傳回并關閉攝像頭,這樣就完成了我們的拍照功能。這裡的$uibmodalinstance

對象是我們項目中打開彈出層的一個對象,用來控制彈出層的顯示。

4. 如何關閉攝像頭

$scope.closecamera = function () { 

            if (mediastream != null) { 

                if (mediastream.stop) { 

                    mediastream.stop(); 

                } 

                $scope.videosrc = ""; 

            } 

            if (track != null) { 

                if (track.stop) { 

                    track.stop(); 

正如前面所說,關閉攝像頭的方式是通過mediastream和track變量,隻不過,track隻能關閉chrome浏覽器中的攝像頭,這也是chrome 45版本以上關閉攝像頭的方式。

5. 內建到andularjs

事實上,前面所說的都是在andularjs中實作的,當然,這裡隻是實作了拍照并傳回拍照資料,我們想要在其他地方也使用,就需要将這部分獨立出

來,這裡我們用到了angularjs中的service機制,将這部分單獨做成一個service并在項目中注入,然後就可以在其他地方調用了。

service注冊: 

app().registerservice("h5takephotoservice", function ($q, $uibmodal) { 

        this.photo = function () { 

            var deferred = $q.defer(); 

            require([config.server + "/com/controllers/photo.js"], function () { 

                $uibmodal.open({ 

                    templateurl: config.server + "/com/views/modal_take_photo.html", 

                    controller: "photomodalcontroller", 

                    windowclass: "modal-photo" 

                }).result.then(function (e) { 

                    deferred.resolve(e); 

                }); 

            }); 

            return deferred.promise; 

    }); 

調用方式:

$scope.takephoto = function () { 

      h5takephotoservice.photo().then(function (res) { 

           if (res != null && res != "") { 

               $scope.myimage = res; 

           } 

      }); 

h5takephotoservice為控制器中注入的拍照service對象,最後處理傳回的圖像資料,設定資料顯示到界面上。

6. 相容問題

主要存在chrome浏覽器中,本地測試時,chrome浏覽器中能夠正常使用,但是部署到伺服器後就不能正常使用,報錯消息

為 [object navigatorusermediaerror],這是因為chrome浏覽器在使用攝像頭時隻支援安全源通路,是以隻能通過

https通路才能正常使用。

最後需要說一下,測試時隻能通過http://url通路才能使用,不能通過file://url方式通路,即我們需要将代碼部署才能通路,可以在visual studio、 java web、php中完成。

作者:楊勇

來源:51cto