AR attempts (1) --- js call camera to the bottom

Recently doing a demo of human gesture recognition with a web end, encountered some pit, record it.
First problem encountered is to call for the end of the camera with js. Here I refer to the EASY-AR's demo
is divided into two files main.js and 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);
     }

Here then I encountered a problem that when the phone visit, Andrews most of the models are possible, but I tested ios models have emerged, the actual camera captures in the region is greater than html, resulting in pages that can move around.

View source, did not think of solutions, so I used my own methods to solve:
First, if only to calculate the middle of the display, how much width should be about 2 end.

this.videoOffWidth = this.videoElement.offsetWidth - window.innerWidth;

Then by setting marginleft, to "cut" to the left.

this.videoElement.style.marginLeft = -this.videoOffWidth/2 + "px";

Html settings can not be sliding around again by giving to "cut" to the right (of course this is only a temporary solution for the problem, but for me this project, this method is good enough.)

body {
    margin: 0;
    padding: 0;
    position:fixed;
    overflow: hidden;
}

So that it can achieve the screen with a camera for the end of the.

Published 57 original articles · won praise 3 · Views 6217

Guess you like

Origin blog.csdn.net/qq_39830579/article/details/97259195