Vue2调用电脑摄像头权限,并拍照

背景:

电脑端需要调取用户摄像头进行拍照


1.封装工具函数------获取用户摄像头设备

/** @desc 获取计算机外设列表 储存摄像头数据 */
getDevices() {
  return new Promise((resolve, reject) => {
    if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
      window.alert("不支持 mediaDevices.enumerateDevices()");
    }
    navigator.mediaDevices
      .enumerateDevices()
      .then(devices => {
        let cameraList = [];
        devices.forEach((device, index) => {
          // 获取摄像头外设 videoinput
          if (device.kind && device.kind === "videoinput") {
            if (device.deviceId) {
              cameraList.push({
                id: device.deviceId,
                label: device.label
              });
            }
          }
        });
        resolve(cameraList);
      })
      .catch(err => {
        console.log(err.name + ": " + err.message);
        reject();
      });
  });
}

2.封装工具函数------获取用户摄像头设备

/** 
 * @desc 获取摄像头权限 getUserMedia 
 * deviceId	getDevices()函数获取的设备id
 * success  调用成功的回调函数
 * error	调用失败的回调函数
*/
getUserMedia(deviceId, success, error) {
  const constraints= {
      audio: false,
  	  video: {
         width: 300,
         height: 200,
         transform: "scaleX(-1)",
         deviceId: deviceId
      }
   };
  if (navigator.mediaDevices.getUserMedia) {
    //最新的标准API
    navigator.mediaDevices
      .getUserMedia(constraints)
      .then(success)
      .catch(error);
  } else if (navigator.webkitGetUserMedia) {
    //webkit核心浏览器
    navigator.webkitGetUserMedia(constraints, success, error);
  } else if (navigator.mozGetUserMedia) {
    //firfox浏览器
    navigator.mozGetUserMedia(constraints, success, error);
  } else if (navigator.getUserMedia) {
    //旧版API
    navigator.getUserMedia(constraints, success, error);
  }
}

3.调用摄像头

/** @desc 摄像头使能封装 */
enableCamera(deviceId) {
  this.getUserMedia(
    deviceId,
    stream => {
      if ("srcObject" in this.thisVideo) {
        this.thisVideo.srcObject = stream;
      } else {
        // 避免在新的浏览器中使用它,新浏览器正在被弃用。没有开启摄像头权限或浏览器版本不兼容
        this.thisVideo.src = window.URL.createObjectURL(stream);
      }
      this.thisVideo.onloadedmetadata = e => {
        this.thisVideo.play();
      };
    },
    error => {
      console.log(`访问用户媒体设备失败${error.name}, ${error.message}`);
      alert("摄像头打开失败,请检查摄像头并点击浏览器地址栏右侧的摄像头标志进行开启设置");
    }
  );
},
// 拍照
handlePhotograph() {
  	this.thisContext.drawImage(this.thisVideo, 0, 0, 300, 200);
 	// 获取图片base64链接;
 	this.imgSrc = this.thisCanvas.toDataURL("image/png", 0.7);
},

完整代码:

<template>
  <div>
    <video id="videoCamera" autoplay></video>
    <img id="save_img" :src="imgSrc" alt="" />
    <canvas
      style="display: none"
      id="canvasCamera"
      :width="videoWidth"
      :height="videoHeight"
    ></canvas>
    <!--确认-->
    <button @click="handlePhotograph">拍照</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      videoWidth: 300,
      videoHeight: 200,
      cameraList: [{ id: "", label: "摄像头1" }],
      currentCamera: "",
      imgSrc: ""
    };
  },

  components: {},

  computed: {},

  mounted() {
    this.getDevices().then(res => {
      if (res.length) {
        this.cameraList = res;
      }
      this.currentCamera = this.cameraList[0].id;
      this.main();
    });
  },

  methods: {
    main() {
      this.thisCanvas = document.getElementById("canvasCamera");
      this.thisContext = this.thisCanvas.getContext("2d");
      this.thisVideo = document.getElementById("videoCamera");
      this.enableCamera(this.currentCamera);
    },
    getDevices() {
      return new Promise((resolve, reject) => {
        if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
          window.alert("不支持 mediaDevices.enumerateDevices()");
        }
        navigator.mediaDevices
          .enumerateDevices()
          .then(devices => {
            let cameraList = [];
            devices.forEach((device, index) => {
              // 获取摄像头外设 videoinput
              if (device.kind && device.kind === "videoinput") {
                if (device.deviceId) {
                  cameraList.push({
                    id: device.deviceId,
                    label: device.label
                  });
                }
              }
            });
            resolve(cameraList);
          })
          .catch(err => {
            console.log(err.name + ": " + err.message);
            reject();
          });
      });
    },
    /**
     * @desc 获取摄像头权限 getUserMedia
     * deviceId	getDevices()函数获取的设备id
     * success  调用成功的回调函数
     * error	调用失败的回调函数
     */
    getUserMedia(deviceId, success, error) {
      const constraints = {
        audio: false,
        video: {
          width: this.videoWidth,
          height: this.videoHeight,
          transform: "scaleX(-1)",
          deviceId: deviceId
        }
      };
      if (navigator.mediaDevices.getUserMedia) {
        //最新的标准API
        navigator.mediaDevices
          .getUserMedia(constraints)
          .then(success)
          .catch(error);
      } else if (navigator.webkitGetUserMedia) {
        //webkit核心浏览器
        navigator.webkitGetUserMedia(constraints, success, error);
      } else if (navigator.mozGetUserMedia) {
        //firfox浏览器
        navigator.mozGetUserMedia(constraints, success, error);
      } else if (navigator.getUserMedia) {
        //旧版API
        navigator.getUserMedia(constraints, success, error);
      }
    } /** @desc 摄像头使能封装 */,
    enableCamera(deviceId) {
      this.getUserMedia(
        deviceId,
        stream => {
          if ("srcObject" in this.thisVideo) {
            this.thisVideo.srcObject = stream;
          } else {
            // 避免在新的浏览器中使用它,新浏览器正在被弃用。没有开启摄像头权限或浏览器版本不兼容
            this.thisVideo.src = window.URL.createObjectURL(stream);
          }
          this.thisVideo.onloadedmetadata = e => {
            this.thisVideo.play();
          };
        },
        error => {
          console.log(`访问用户媒体设备失败${error.name}, ${error.message}`);
          alert("摄像头打开失败,请检查摄像头并点击浏览器地址栏右侧的摄像头标志进行开启设置");
        }
      );
    },
    // 拍照
    handlePhotograph() {
      this.thisContext.drawImage(this.thisVideo, 0, 0, 300, 200);
      // 获取图片base64链接;
      this.imgSrc = this.thisCanvas.toDataURL("image/png", 0.7);
    }
  }
};
</script>
<style lang="scss" scoped></style>
### 访问使用外部USB摄像头拍照 为了实现在Vue.js项目中通过电脑调用外接摄像头进行拍照的功能,可以利用WebRTC技术中的`navigator.mediaDevices.getUserMedia()`方法来获取媒体设备权限。此API允许网页请求访问用户的摄像机和麦克风[^1]。 下面是一个简单的实现方案: #### 创建一个用于展示视频流以及拍照按钮的组件 ```html <template> <div> <video ref="videoPlayer" autoplay playsinline></video> <button @click="capture">Capture</button> <canvas ref="photoCanvas"></canvas> </div> </template> <script> export default { data() { return { stream: null, }; }, methods: { async startCamera() { try { this.stream = await navigator.mediaDevices.getUserMedia({ video: true }); const videoElement = this.$refs.videoPlayer; videoElement.srcObject = this.stream; } catch (error) { console.error('Error accessing media devices.', error); } }, capture() { const canvasElement = this.$refs.photoCanvas; const videoElement = this.$refs.videoPlayer; canvasElement.width = videoElement.videoWidth; canvasElement.height = videoElement.videoHeight; const context = canvasElement.getContext('2d'); context.drawImage(videoElement, 0, 0, canvasElement.width, canvasElement.height); // 可选:转换成图片文件或者其他操作 const photoDataUrl = canvasElement.toDataURL('image/png'); console.log(photoDataUrl); // 这里只是打印出来,在实际应用中可以根据需求处理这张照片 } }, mounted() { this.startCamera(); }, beforeDestroy() { if (this.stream) { this.stream.getTracks().forEach(track => track.stop()); } } }; </script> <style scoped> /* 添加一些样式让界面更友好 */ video, canvas { width: 100%; max-width: 640px; margin-bottom: 1rem;} button { display:block;margin:auto;padding:.5em 1em;font-size:1rem;border:none;background-color:#007bff;color:white;border-radius:.25rem;cursor:pointer;text-align:center;} </style> ``` 上述代码创建了一个Vue单文件组件,其中包含了启动摄像头、显示实时预览画面以及捕捉图像到画布上的逻辑。当页面加载完成之后会自动尝试打开摄像头;点击“Capture”按钮则会在画布上绘制当前帧的画面,将其转化为PNG格式的数据URL以便进一步处理或上传。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值