最近、いくつかのピットが発生したウェブ端と人間のジェスチャー認識のデモをやって、それを記録。
最初に検出された問題は、JSとカメラの終了を呼び出すことです。ここで私は、EASY-ARのデモを参照してください
2つのファイルmain.jsとClassAR.jsに分かれています
main.js:
function firstOpenCamera(){
classAR.listCamera(videoDevice)
.then(msg => {
classAR.openCamera(JSON.parse(videoDevice[0].value))
.then(msg => {
console.info(msg);
}).catch(err => {
console.info(err);
});
})
.catch(err => {
// 没有找到摄像头
console.info(err);
});
}
document.querySelector('#btn_changeCamera').addEventListener('click', function () {
// 打开摄像头
// 打开后置摄像头参数: {audio: false, video: {facingMode: {exact: 'environment'}}}
if(videoDevice.length == 0 || videoDevice.length == 1)
return;
nowVideo = nowVideo == 0? 1 : 0; //切换当前摄像头
classAR.openCamera(JSON.parse(videoDevice[nowVideo].value))
.then(msg => {
console.info(msg);
}).catch(err => {
console.info(err);
});
});
// 开启识别
document.querySelector('#btn_check').addEventListener('click', () => {
classAR.startRecognize(classAR,(msg) => {
console.info(msg);
});
}, false);
classAR:
export default class ClassAR {
constructor(interval,nowBodyModel) {
this.isRecognizing = false;
// 前/后置摄像头
this.cameras = ["user", "environment"];
this.interval = interval;
this.videoOffWidth = 0;
this.videoOffHeight = 0;
}
listCamera(videoDevice) {
return new Promise((resolve, reject) => {
navigator.mediaDevices.enumerateDevices()
.then((devices) => {
let index = 0;
devices.find((device) => {
if (device.kind === 'videoinput') {
const option = document.createElement('option');
// 在iOS12.2上deviceId为空
if (device.deviceId == '') {
option.text = device.label || 'camera ' + this.cameras[index];
option.value = JSON.stringify({
audio: false,
video: {facingMode: {exact: this.cameras[index]}}
});
index++;
} else {
option.text = device.label || 'camera ' + (videoDevice.length + 1).toString();
option.value = JSON.stringify({
audio: false,
video: {deviceId: {exact: device.deviceId}}
});
}
// 将摄像头信息存储在select元素中,方便切换前、后置摄像头
videoDevice.push(option);
}
return false;
});
if (videoDevice.length === 0) {
reject('没有可使用的视频设备');
} else {
this.initVideo();
//this.initCanvas();
resolve(true);
}
}).catch(err => {
reject(err);
});
});
}
/**
* 打开摄像头
* 摄像头设置参数请查看: https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints
* @param videoDeviceIndex
* @returns {Promise<T>}
*/
openCamera(constraints) {
// 如果是切换摄像头,则需要先关闭。
if (this.videoElement && this.videoElement.srcObject) {
this.videoElement.srcObject.getTracks().forEach(track => {
track.stop();
});
}
return new Promise((resolve, reject) => {
navigator.mediaDevices.getUserMedia(constraints)
.then(stream => {
this.videoElement.srcObject = stream;
this.videoElement.style.display = 'block';
this.videoElement.play();
this.videoElement.onloadedmetadata = () => {
const cameraSize = {
width: this.videoElement.offsetWidth,
height: this.videoElement.offsetHeight
};
console.info(JSON.stringify(cameraSize));
if (window.innerWidth < window.innerHeight) {
// 竖屏
if (cameraSize.height < window.innerHeight) {
this.videoElement.setAttribute('height', window.innerHeight.toString() + 'px');
this.videoOffWidth = this.videoElement.offsetWidth - window.innerWidth;
this.videoElement.style.marginLeft = -this.videoOffWidth/2 + "px";
//this.canvasElement.style.marginLeft = -(cameraSize.width - window.innerWidth) + "px";
}
} else {
// 横屏
if (cameraSize.width < window.innerWidth) {
this.videoElement.setAttribute('width', window.innerWidth.toString() + 'px');
this.videoOffHeight = this.videoElement.offsetHeight - window.innerHeight + "px";
this.videoElement.style.marginTop = -this.videoOffHeight + "px";
//this.canvasElement.style.marginTop = -(cameraSize.width - window.innerWidth) + "px";
}
}
resolve(true);
this.initCanvas();
};
})
.catch(err => {
reject(err);
});
});
}
/**
* 截取摄像头图片
* @returns {HTMLImageElement}
*/
captureVideo() {
//this.canvasContext.drawImage(this.videoElement, this.videoOffWidth / 2, 0 , window.innerWidth,620 , 0 , 0 ,window.innerWidth,window.innerHeight);
this.canvasContext.drawImage(this.videoElement,0,0,window.innerWidth,window.innerHeight);
//this.canvasElement.style.marginLeft = - this.videoOffWidth/2 + 'px';
//this.canvasContext2.drawImage(this.canvasElement,0,0,300,window.innerHeight,0,0,300,window.innerHeight);
//return this.canvasElement.toDataURL('image/jpeg', 0.5).split('base64,')[1];
let image_64 = this.canvasElement.toDataURL('image/jpeg');
let image = new Image();
image.src = image_64;
this.canvasElement.style.display = "none";
let newImagePromise = this.cutImage(image);
return newImagePromise;
}
/**
* 创建视频详情元素,播放摄像头视频流
*/
initVideo() {
/*this.videoElement = document.createElement('video');
this.videoElement.setAttribute('playsinline', 'playsinline');
document.body.appendChild(this.videoElement);*/
// this.videoElement = document.createElement('video');
this.videoElement = document.getElementById('video');
this.videoElement.setAttribute('playsinline', 'playsinline');
//this.videoElement.setAttribute('width', window.innerWidth.toString() + 'px');
//this.videoElement.setAttribute('height', window.innerHeight.toString() + 'px');
document.body.appendChild(this.videoElement);
}
/**
* 创建canvas,截取摄像头图片时使用
*/
initCanvas() {
// this.canvasElement = document.createElement('canvas');
this.canvasElement = document.getElementById('canvas');
this.canvasElement.setAttribute('width', window.innerWidth.toString() + 'px');
this.canvasElement.setAttribute('height', window.innerHeight.toString() + 'px');
this.canvasContext = this.canvasElement.getContext('2d');
this.canvasElement2 = document.getElementById('canvas2');
this.canvasElement2.setAttribute('width', window.innerWidth + 'px');
this.canvasElement2.setAttribute('height', window.innerHeight+ 'px');
this.canvasContext2 = this.canvasElement2.getContext('2d');
// document.body.appendChild(this.canvasElement);
}
ここでは、私は問題が発生したときに、電話訪問、アンドリュースは、ほとんどのモデルの可能性ですが、私はモデルが浮上しているIOSをテストしていること、地域の実際のカメラのキャプチャは動き回ることができますページで、その結果、HTMLよりも大きくなります。
私は解決するために自分自身のメソッドを使用して表示ソースは、解決策を考えていなかった:
まず、唯一のどのくらいの幅が2エンドであるべきである、ディスプレイの中央を計算する場合。
this.videoOffWidth = this.videoElement.offsetWidth - window.innerWidth;
そして、左に「カット」に、marginleftを設定することもできます。
this.videoElement.style.marginLeft = -this.videoOffWidth/2 + "px";
Htmlの設定が右側に「カット」を与えることによって、再び周りにスライドすることができません(もちろん、この問題の唯一の一時的な解決策ですが、私、このプロジェクトのために、この方法は十分に良いです。)
body {
margin: 0;
padding: 0;
position:fixed;
overflow: hidden;
}
それはの終わりのためのカメラで画面を実現することができるように。