浏览器调起摄像头

浏览器调起摄像头

<template>
  <div class="body">
    这里什么都没有
    <video id="videoCamera" class="video"></video>
    <button @click="getCompetence" class="btn">打开摄像头</button>
    <button @click="stopNavigator" class="btn">关闭摄像头</button>
    <button @click="setImage" class="btn">点击截图</button>
    {
    
    {
    
     imgSrc }}
    <canvas class="canvas" id="canvasCamera"></canvas>
  </div>
</template>

<script>
export default {
    
    
  data() {
    
    
    return {
    
    
      videoWidth: 500,
      videoHeight: 300,
      number: 0,
      hours: 0,
      minutes: 0,
      seconds: 0,
      run: false,
      imgSrc: '',
      flag: true,
      thisCancas: null,
      thisContext: null,
      thisVideo: null,
      userInfo: {
    
    
        imgStr: ""
      },
      videoState: true
    }
  },
  methods: {
    
    
    // 调用摄像头
    getCompetence() {
    
    
      this.videoState = false
      var _this = this
      this.thisCancas = document.getElementById('canvasCamera')
      this.thisContext = this.thisCancas.getContext('2d')
      this.thisVideo = document.getElementById('videoCamera')

      // 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象
      if (navigator.mediaDevices === undefined) {
    
    
        navigator.mediaDevices = {
    
    }
      }
      // 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象
      // 使用getUserMedia,因为它会覆盖现有的属性。
      // 这里,如果缺少getUserMedia属性,就添加它。
      if (navigator.mediaDevices.getUserMedia === undefined) {
    
    
        navigator.mediaDevices.getUserMedia = function (constraints) {
    
    
          // 首先获取现存的getUserMedia(如果存在)
          var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia
          // 有些浏览器不支持,会返回错误信息
          // 保持接口一致
          console.log('viedo', getUserMedia);
          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)
          })
        }
      }
      //使用此方式获取本地音频视频输入输出设备,找到要使用的设备id,方式见下图
      var enumeratorPromise = navigator.mediaDevices.enumerateDevices()
      console.log(enumeratorPromise)
      //把上面获取到的设备deviceId填入下面video的deviceId中,就可以选择要调用的摄像头了
      var constraints = {
    
     audio: false, video: {
    
     deviceId: 'becf7e45fe56e42bcb4ec3f78b1b6b0fcffd6c6ccd890d30fffc2430a92c99bb', width: this.videoWidth, height: this.videoHeight } }
      navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
    
    
        // 旧的浏览器可能没有srcObject
        if ('srcObject' in _this.thisVideo) {
    
    
          _this.thisVideo.srcObject = stream
        } else {
    
    
          // 避免在新的浏览器中使用它,因为它正在被弃用。
          _this.thisVideo.src = window.URL.createObjectURL(stream)
        }
        _this.thisVideo.onloadedmetadata = function (e) {
    
    

          if (_this.flag == true) {
    
    
            _this.thisVideo.play();
            _this.flag = false;
          }
          else {
    
    
            _this.thisVideo.pause()
            _this.flag = true;
          }

        }
      }).catch(err => {
    
    
        console.log(err)
      })
    },
    // 关闭摄像头
    stopNavigator() {
    
    
      this.videoState = true
      this.thisVideo.srcObject.getTracks()[0].stop()
    },
    // 截图
    setImage() {
    
    
      var _this = this
      _this.imgSrc = '';
      // 点击,canvas画图
      _this.thisContext.drawImage(_this.thisVideo, 0, 0, _this.videoWidth, _this.videoHeight)
      // 获取图片base64链接

      _this.imgSrc = this.thisCancas.toDataURL('image/png')//_this.imgSrc为解码得到的base64编码格式的图片
      //转blob的url
      // const blob = base64ToBlob(base64String);
      // const imageUrl = blobToUrl(blob);
      // console.log(imageUrl);
      // _this.imgSrc = imageUrl

      console.log('picture', _this.imgSrc)
      // this.$emit('setImgSrc', _this.imgSrc)
      console.log('转换', this.dataURLtoFile(_this.imgSrc, 'file'))
    },
    clearImgSrc() {
    
    
      this.imgSrc = ''
    },

    //base64转文件
    dataURLtoFile(urlData, fileName) {
    
    
      let arr = urlData.split(',');
      let mime = arr[0].match(/:(.*?);/)[1];
      let bytes = atob(arr[1]); // 解码base64
      let n = bytes.length
      let ia = new Uint8Array(n);
      while (n--) {
    
    
        ia[n] = bytes.charCodeAt(n);
      }
      console.log('转换成功');
      return new File([ia], fileName, {
    
     type: mime });

    },
    base64ToBlob(base64) {
    
    
      const byteCharacters = atob(base64);
      const byteArrays = [];

      for (let offset = 0; offset < byteCharacters.length; offset += 512) {
    
    
        const slice = byteCharacters.slice(offset, offset + 512);

        const byteNumbers = new Array(slice.length);
        for (let i = 0; i < slice.length; i++) {
    
    
          byteNumbers[i] = slice.charCodeAt(i);
        }

        const byteArray = new Uint8Array(byteNumbers);
        byteArrays.push(byteArray);
      }

      const blob = new Blob(byteArrays, {
    
     type: 'image/jpeg' }); // 根据实际的 Base64 字符串类型设置对应的 MIME 类型
      return blob;
    },

    blobToUrl(blob) {
    
    
      const url = URL.createObjectURL(blob);
      return url;
    }




  }
}
</script>

<style lang="less">
.body {
    
    
  display: flex;
  flex-direction: column;
  justify-content: center;
  // align-items: center;
  width: 100%;
  height: 100%;
}

.video {
    
    
  width: 500px;
  height: 300px;
}

.canvas {
    
    
  width: 500px;
  height: 100%;
}

.btn {
    
    
  width: 100px;
  height: 20px;
}
</style>


参考:
[【前端vue——系列6】vue连接摄像头并实现摄像头暂停,计时,截图到本地等功能](https://blog.csdn.net/yangyaning123/article/details/118071503)

猜你喜欢

转载自blog.csdn.net/Ann_52547/article/details/132605686