AngularJS中使用HTML5攝像頭拍照

2016-02-21    分類:WEB開發、程式設計開發、首頁精華2人評論發表於2016-02-21

本文由碼農網 – 楊勇原創,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃

1. 專案背景

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

這是在AngularJs中成功實現呼叫攝像頭拍照並截圖上傳的例圖:

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中完成。

本文連結:http://www.codeceo.com/article/angularjs-html5-take-photo.html
本文作者:碼農網 – 楊勇
原創作品,轉載必須在正文中標註並保留原文連結和作者等資訊。]

相關文章