項目背景
公司開發一個網站,在做帳戶圖片修改的時候領導提到增加一個由網路攝影機拍照實現修改頭像的功能。因為我們網站是基於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瀏覽器、Firefox瀏覽器和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中完成。