1,class类的定义
class WebAR { /** * 初始化Web AR * @param interval 识别间隔(毫秒) * @param recognizeUrl 识别服务地址 * @param isDebug 是否输入调试信息 * @param token 非必需,使用token认证识别 */ constructor(interval, recognizeUrl, token) { this.isRecognizing = false; // 前/后置摄像头 this.cameras = ["user", "environment"]; this.interval = interval; this.recognizeUrl = recognizeUrl; this.token = token; } /** * 列表设备上的所有摄像头 * @param videoDevice * @returns {Promise<T>} */ listCamera(videoDevice) { return new Promise((resolve, reject) => { navigator.mediaDevices.enumerateDevices() .then((devices) => { let index = 1; 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.appendChild(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 = { 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'); } } else { // 横屏 if (cameraSize.width < window.innerWidth) { this.videoElement.setAttribute('width', window.innerWidth.toString() + 'px'); } } resolve(true); }; }) .catch(err => { reject(err); }); }); } /** * 截取摄像头图片 * @returns {string} */ captureVideo() { this.canvasContext.drawImage(this.videoElement, 0, 0, this.videoElement.offsetWidth, this.videoElement.offsetHeight); // console.log(this.canvasElement.toDataURL('image/jpeg', 0.5).split('base64,')[1]); return this.canvasElement.toDataURL('image/jpeg', 0.5).split('base64,')[1]; } /** * 创建视频详情元素,播放摄像头视频流 */ initVideo() { this.videoElement = document.createElement('video'); this.videoElement.setAttribute('playsinline', 'playsinline'); document.body.appendChild(this.videoElement); } /** * 创建canvas,截取摄像头图片时使用 */ initCanvas() { this.canvasElement = document.createElement('canvas'); this.canvasElement.setAttribute('width', window.innerWidth.toString() + 'px'); this.canvasElement.setAttribute('height', window.innerHeight.toString() + 'px'); this.canvasContext = this.canvasElement.getContext('2d'); // document.body.appendChild(this.canvasElement); } /** * 识别 * @param callback */ startRecognize(callback) { this.timer = window.setInterval(() => { // 等待上一次识别结果 if (this.isRecognizing) { return; } this.isRecognizing = true; // 从摄像头中抓取一张图片 const image = { image: this.captureVideo() }; // 发送到服务器识别 this.httpPost(image) .then((msg) => { this.stopRecognize(); callback(msg); }) .catch((err) => { this.isRecognizing = false; console.info(err); }); }, this.interval); } /** * 停止识别 */ stopRecognize() { if (this.timer) { window.clearInterval(this.timer); this.isRecognizing = false; } } httpPost(image) { return new Promise((resolve, reject) => { const http = new XMLHttpRequest(); http.onload = () => { try { const msg = JSON.parse(http.responseText); if (http.status === 200) { if (msg.statusCode === 0) { resolve(msg.result); } else { reject(msg); } } else { reject(msg); } } catch (err) { reject(err); } }; http.onerror = (err) => { reject(err); }; http.open('POST', this.recognizeUrl); http.setRequestHeader('Content-Type', 'application/json;Charset=UTF-8'); if (this.token) { // 将云识别认证token写在请求头中 http.setRequestHeader('Authorization', this.token); } http.send(JSON.stringify(image)); }); } } //# sourceMappingURL=webar.js.map
2,类的创建和调用
// 别间隔时间(毫秒), 识别服务地址 // const webAR = new WebAR(1000, '/webar/recognize'); const webAR = new WebAR(1000, url, token); // 列出并打开设备上的摄像头 document.querySelector('#openCamera').addEventListener('click', function () { const videoSelect = document.querySelector('#videoDevice'); webAR.listCamera(videoSelect) .then(msg => { // 隐藏"打开摄像头"按钮 this.style.display = 'none'; videoSelect.style.display = 'inline-block'; document.querySelector('#start').style.display = 'inline-block'; document.querySelector('#stop').style.display = 'inline-block'; videoSelect.onchange = () => { webAR.openCamera(JSON.parse(videoSelect.value)); }; // 打开摄像头 // 打开后置摄像头参数: {audio: false, video: {facingMode: {exact: 'environment'}}} webAR.openCamera(JSON.parse(videoSelect.value)) .then(msg => { console.info(msg); }).catch(err => { console.info(err); }); }) .catch(err => { // 没有找到摄像头 console.info(err); }); console.log("list0"); }); // 开启识别 document.querySelector('#start').addEventListener('click', () => { webAR.startRecognize((msg) => { console.info(msg); alert('识别成功'); }); }, false); // 暂停识别 document.querySelector('#stop').addEventListener('click', () => { webAR.stopRecognize(); }, false); //# sourceMappingURL=app.js.map