一.首先在老版本的angular中,无法使用document.getElementById等获取dom元素,在网上找了很多方法,发现都没有用(比如angualr.element(document.getElementById),还有网上查找的方法基本是使用组件的形式获取(ElementRef,ViewChild).
解决办法:只能在video标签给它的高度超过按钮,使得button按钮实际点击的是video标签。代码如下;
html:
<video id="openCamera" style="width: 170px; height: 200px; position:absolute;right: 0; z-index: 9999; cursor: pointer;" ng-click="openVideo($event)" ng-if="isCamera"></video>
<div style="position: absolute;bottom: -25px;width: 100%;">
<p style="text-align: center;cursor: pointer;background: rgba(0,0,0,.3);color: #fff;width: 100%;z-index: 99;" ng-click="openCamera()" ng-if="!isOpenCamera">打开摄像头</p>
<p style="text-align: center;cursor: pointer;background: rgba(0,0,0,.3);color: #fff;width: 100%;z-index: 99;" ng-click="CameraClick()" ng-if="isOpenCamera">点击拍照</p>
</div>
js:
$scope.openVideo = function(e) {
if(!$scope.isOpenCamera) {
$scope.openCamera(e);
}else {
$scope.CameraClick(e)
}
}
$scope.openCamera = function(e) {
$scope.isCamera = true;
if(!e) return
if(navigator.mediaDevices === undefined) {
navigator.mediaDevices = {};
}
if(navigator.mediaDevices.getUserMedia === undefined) {
navigator.mediaDevices.getUserMedia = function (constraints) {
var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
if(!getUserMedia) {
return Promise.reject(new Error('getUserMedia is not implemented in this browser'))
}
//否则,使用Promise将调用包装到旧的navigator.getUserMedia
return new Promise(function (resolve, reject) {
getUserMedia.call(navigator, constraints, resolve, reject);
});
}
}
const constraints = {
video: true,
audio: false
}
let video = e.target;
$scope.video = e.target;
let promise = navigator.mediaDevices.getUserMedia(constraints);
promise.then( stream => {
if("srcObject" in video) {
video.srcObject = stream;
}else {
video.src = window.URL.createObjectURL(stream);
}
video.onloadedmetadata = function(e) {
$scope.isOpenCamera = true;
video.play()
}
} ).catch(err => {
console.error(err.name + ": " + err.message);
})
}
// 点击拍照
$scope.CameraClick = function(e) {
if(!e) return
if(navigator.mediaDevices === undefined) {
navigator.mediaDevices = {};
}
if(navigator.mediaDevices.getUserMedia === undefined) {
navigator.mediaDevices.getUserMedia = function (constraints) {
var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
if(!getUserMedia) {
return Promise.reject(new Error('getUserMedia is not implemented in this browser'))
}
//否则,使用Promise将调用包装到旧的navigator.getUserMedia
return new Promise(function (resolve, reject) {
getUserMedia.call(navigator, constraints, resolve, reject);
});
}
}
let video = e.target;
const constraints = {
video: true,
audio: false
}
// 通过canvas捕捉video流,生成base64格式照片
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
canvas.width = 170;
canvas.height = 170;
canvas.style.display = "none";
context.drawImage(video,0,0,canvas.width,canvas.height)
let image = canvas.toDataURL('image/png')
console.log(image)
let formData = $scope.dataURLtoFile(image);
formData.name = "头像.png"
if(formData) {
$scope.upload(formData);
setTimeout(() => {
let promise = navigator.mediaDevices.getUserMedia(constraints);
promise.then( stream => {
stream.getVideoTracks().forEach(track => track.stop())
stream = null;
$scope.video = null;
video.srcObject = null;
$scope.isOpenCamera = false;
} )
},2000)
}
}
// base64 转文件流
$scope.dataURLtoFile = function(dataurl) {
var arr = dataurl.split(","),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {
type: mime,
});
}