浏览器调起摄像头

news/2024/7/10 1:17:29 标签: vue

浏览器调起摄像头

<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)

http://www.niftyadmin.cn/n/4987843.html

相关文章

容器权限降级为 op 用户

容器权限降级为 op 用户 更新 Docker Compose 配置文件&#xff1a; 请确保已提供的 docker-compose.yml 文件已准备好&#xff0c;并覆盖了原先的配置文件。 cd /home/op/compose设置文件和文件夹权限&#xff1a; 在 Linux 环境中&#xff0c;按照以下步骤逐一执行命令。在需…

第二部分:模型驱动设计

目录 关键的概念 之间的关系 关键的概念 Service&#xff08;领域服务&#xff09;、Entity&#xff08;实体&#xff09;、Value Object&#xff08;值对象&#xff09;、领域事件、 Aggregate&#xff08;聚合&#xff09;、 Aggregate root&#xff08;聚合根&#xff09;、…

Ract父组件调用子组件方法

1、父子组件都是class 父组件 import React, {Component} from react; import {Button} from antd; import TableList from ./TableList;export default class ParentPage extends Component {childRef React.createRef();render() {return (<div><Button onClick{…

使用dpkg命令离线安装软件包

使用dpkg命令离线安装软件包 有时目标机器处于脱机状态或无法接入公网&#xff0c;无法使用apt命令直接在线安装软件包&#xff0c;这时我们可以借助另一台能联网的机器首先下载软件包以及需要的依赖包&#xff0c;然后将软件包和依赖包全部复制到目标机器上&#xff0c;最后使…

基于pytorch LSTM 的股票预测

学习记录于《PyTorch深度学习项目实战100例》 https://weibaohang.blog.csdn.net/article/details/127365867?ydrefereraHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzQ3MjU2MTYyL2NhdGVnb3J5XzEyMDM2MTg5Lmh0bWw%2Fc3BtPTEwMDEuMjAxNC4zMDAxLjU0ODI%3D 1.tushare Tushare是一个免费、…

ssm计算机网络课程试卷生成器系统源码

ssm计算机网络课程试卷生成器系统源码099 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm package com.controller;import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays;…

nullfilter正常加载,callback不生效

代码网上都有&#xff0c;就讲一下解决安装问题&#xff1a; 1.mini filter driver 安装需要通过inf 文件来&#xff0c;就是要在注册表中添加一下额外的键值。右击inf文件&#xff0c;点击安装。 2&#xff0c;下载微软开源项目中的nullfilter.inf,修改一下&#xff1a;​​…

v-model和.sync的区别

//父组件 <son :valuenum inpute>nume /> <!--v-model 是一个语法糖 它的本质是做了两件事情 1.绑定一个value属性给子组件 2.绑定一个input事件 子组件触发后重新赋值 --> <son v-modelnum /> <!--v-model 也有一些限制 1.绑定的属性必须叫value 2.事…