vue使用navigator.mediaDevices.getUserMedia调用相机功能

news2024/11/25 16:47:36

目录

前言:

API:

API简单示例:

拍照功能 

实现效果:


 

前言:

本文将介绍Vue中如何使用navigator.mediaDevices.getUserMedia调用相机功能,实现拍照使用实例,需要的朋友可以参考一下。

注意:

Vue 调用本地摄像头实现拍照功能,由于调用摄像头有使用权限,只能在本地运行,线上需用 https 域名才可以使用。


API:

Navigator.mediaDevices.getUserMedia()是一种用于访问流媒体设备(如摄像机或麦克风)的API,它是Navigator.mediaDevices API的一部分。它允许网页访问摄像头和/或麦克风,并捕获实时流视频/音频。

此API采用异步方式,通过返回一个Promise来提供访问流媒体设备的权限。如果用户允许,API将返回一个MediaStream对象,该对象可以进一步用于捕获视频和音频。

具体使用方法:MediaDevices.getUserMedia() - Web API 接口参考 | MDN (mozilla.org)


API简单示例:

以下是一个使用Vue.js调用相机功能的示例:

<template>
  <div>
    <video ref="video" autoplay></video>
    <button @click="startCamera">启动相机</button>
    <button @click="stopCamera">关闭相机</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      cameraStream: null,
    };
  },
  methods: {
    async startCamera() {
      try {
        const stream = await navigator.mediaDevices.getUserMedia({
          audio: false,
          video: true,
        });
        this.cameraStream = stream;
        this.$refs.video.srcObject = stream;
      } catch (error) {
        console.error(error);
      }
    },
    stopCamera() {
      if (this.cameraStream) {
        this.cameraStream.getTracks()[0].stop();
        this.cameraStream = null;
      }
    },
  },
};
</script>

在上面的代码中,我们首先在模板中添加一个视频元素,该元素被引用为“video”。我们还添加了两个按钮来启动和关闭相机。

在数据属性中,我们定义了一个名为cameraStream的变量,用于存储从相机捕获的视频流。

在startCamera方法中,我们首先使用await关键字调用navigator.mediaDevices.getUserMedia()方法,传递一个选项对象,其中audio属性设置为false,因为我们不需要捕获音频,video属性设置为true,因为我们需要捕获视频。

如果用户允许访问相机,方法将返回一个MediaStream对象,我们将其存储在cameraStream变量中并将其作为“video”元素的源对象。

在stopCamera方法中,我们首先检查cameraStream是否存在,如果存在,则使用getTracks()[0].stop()方法停止从相机捕获的视频流,并将cameraStream设置为null。


拍照功能 

完整示例:

<template>
  <div id="body">
    <div class="body">
      <div class="camera">
        <video ref="video"></video>
        <canvas
          style="display: none"
          id="canvasCamera"
          ref="canvasDom"
        ></canvas>
      </div>
      <div class="img_body">
        <div class="img_content">
          <div class="image" v-for="(item, index) in image" :key="index">
            <img :src="item" alt="" />
          </div>
        </div>
      </div>
      <div>
        <button @click="open">打开相机</button>
        <button @click="takePhoto">拍照</button>
        <button @click="CloseCamera">关闭相机</button>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from "vue";
import { useRouter } from "vue-router";
const video = ref(null);
const canvasDom = ref(null);
const router = useRouter();
const mediaStreamTrack = ref({});
const video_stream = ref("");
const imgSrc = ref("");
const image = ref([]);
const front = ref(true);
onMounted(() => {
  getCamera();
});
// 打开相机
const open = () => {
  getCamera();
};
const getCamera = () => {
  if (navigator.mediaDevices) {
    navigator.mediaDevices
      .getUserMedia({ video: true })
      .then((stream) => {
        // 摄像头开启成功
        video.value.srcObject = stream;
        video.value.play();
      })
      .catch((err) => {
        console.log(err);
      });
  }
};
// 拍照 绘制图片
const takePhoto = () => {
  // 设置画布大小与摄像大小一致
  canvasDom.value.width = video.value.videoWidth;
  canvasDom.value.height = video.value.videoHeight;
  // 执行画的操作
  canvasDom.value.getContext("2d").drawImage(video.value, 0, 0);
  // 将结果转换为可展示的格式
  imgSrc.value = canvasDom.value.toDataURL("image/webp");
  console.log(imgSrc.value);
  image.value.push(imgSrc.value);
};
// 关闭摄像头
const CloseCamera = () => {
  console.log("关闭摄像头");
  video.value.srcObject.getTracks()[0].stop();
};
</script>


<style scoped>
#body {
  width: 100%;
  display: flex;
  justify-content: center;
}
button {
  width: 60px;
  height: 25px;
  background-color: rgb(86, 250, 174);
  margin: 5px;
  border-radius: 5px;
}
.camera {
  margin-top: 10px;
}
.camera video {
  border-radius: 5px;
}
.img_body {
  width: 100%;
}
.img_content {
  width: 100%;
  display: flex;
}
.image {
  width: 100px;
  height: 100px;
  display: flex;
  justify-content: center;
  align-items: center;
}
.image img {
  width: 80px;
  height: 80px;
  border-radius: 5px;
}
</style>

navigator.mediaDevices.getUserMedia切换手机前后摄像头:

前置摄像头:

navigator.mediaDevices
      .getUserMedia({ video: true })
      .then((stream) => {
        // 摄像头开启成功
        video.value.srcObject = stream;
        video.value.play();
      })
      .catch((err) => {
        console.log(err);
      });

后置摄像头: 

navigator.mediaDevices
      .getUserMedia({
        audio: true,
        video: { facingMode: { exact: "environment" } },
      })
      .then((stream) => {
        // 摄像头开启成功
        video.value.srcObject = stream;
        video.value.play();
      })
      .catch((err) => {
        console.log(err);
      });

实现效果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1219679.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

02_SHELL编程之流程控制和循环语句

课程目标 熟悉流程控制语句基本语法&#xff0c;如if…else… 掌握for循环语句的基本语法结构 掌握while和until循环语句的基本语法结构 ###一、流程控制语句 ####1. 基本语法结构 F: false 假 T: true 真 if [ condition ];thencommandcommand fi ​ [ 条件 ] &&a…

NSSCTF第12页(3)

[NSSCTF 2nd]php签到 首先&#xff0c;代码定义了一个名为 waf 的函数&#xff0c;用于执行一个简单的文件扩展名检查来防止上传恶意文件。 $black_list 是一个存储不允许的文件扩展名的数组&#xff0c;如 “ph”、“htaccess” 和 “ini”。 pathinfo($filename, PATHINF…

拥抱开源生态,算能携手软件所 PLCT 实验室联合举办 RISC-V 软件移植优化锦标赛

&#xff08;引言&#xff09;为推动RISC-V软件生态加速发展&#xff0c;算能作为RISC-V生态的领先企业&#xff0c;与RISC-V 中国社区、中科院软件所PLCT实验室联合发起“RISC-V软件移植及优化锦标赛”活动&#xff0c;以桌面和服务器软件生态为重点&#xff0c;在编译器、运行…

2023-11-17 LeetCode每日一题(最大和查询)

2023-11-17每日一题 一、题目编号 2736. 最大和查询二、题目链接 点击跳转到题目位置 三、题目描述 给你两个长度为 n 、下标从 0 开始的整数数组 nums1 和 nums2 &#xff0c;另给你一个下标从 1 开始的二维数组 queries &#xff0c;其中 queries[i] [xi, yi] 。 对于…

SOLIDWORKS参数化设计之主参数设置

SOLIDWORKS参数化设计是通过主参数来驱动整个模型的变化&#xff0c;因此确定主参数是很重要的部分。主参数可以是数值&#xff0c;也可以是条件&#xff0c;可以手动输入&#xff0c;也可以做成下拉列表。今天我们就来看看主参数的下拉列表是如何做到的。 SolidKits.AutoWork…

近期局势较多变化 适合黄金代理入场吗?

进入本年的四季度后&#xff0c;中东局势出现了比较大的变化。首先&#xff0c;巴以冲突不断的加剧&#xff0c;而且马来西亚的林吉特出现大幅贬值&#xff0c;甚至有市场论调认为&#xff0c;亚洲金融危机可能会重新点燃。从这个角度来说&#xff0c;整体的市场环境是很动荡的…

波卡三季度报告:已实现白皮书目标,异步支持与应用链技术推进

作者&#xff1a;Nicholas Garcia&#xff0c;Messari 研究分析师 编译&#xff1a;OneBlock 来源&#xff1a;https://messari.io/report/state-of-polkadot-q3-2023 知名分析平台 Messari 发布了 Polkadot 2023 年第三季度报告&#xff0c;分析了波卡的关键数据指标以及网…

【蓝桥杯选拔赛真题23】C++计算24 第十二届蓝桥杯青少年创意编程大赛C++编程选拔赛真题解析

C/C++计算24 第十二届蓝桥杯青少年创意编程大赛C++选拔赛真题 一、题目要求 1、编程实现 “计算 24”是一个流传已久的数字游戏,小蓝最近对此痴迷不已 游戏规则是:从 1~10 之间的自然数任意拿出 4 个数(4 个数各不相同,顺序随机),进行加、减、乘三种运算(使用某种运算…

0基础如何学习软件测试?10分钟给你安排明白

先上一张学习路线&#xff1a; 在测试行业已经呆了5年多了&#xff0c;也算得上行业经验资深了吧&#xff0c;基本上也是摸清了这个行业的发展。 所以今天也想对有转行想法的朋友分享一下经验&#xff0c;能够让你对这个行业有个大致的了解和对以后的发展有所规划&#xff0c;…

9.3 【MySQL】系统表空间

了解完了独立表空间的基本结构&#xff0c;系统表空间的结构也就好理解多了&#xff0c;系统表空间的结构和独立表空间基本类似&#xff0c;只不过由于整个MySQL进程只有一个系统表空间&#xff0c;在系统表空间中会额外记录一些有关整个系统信息的页面&#xff0c;所以会比独立…

Android Proguard混淆

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、语法规则3.1 输入/输出选项3.2 保留选项3.3 缩…

车载终端功能盘点(车载终端工业行业解决方案案例)

​ 随着车联网的蓬勃发展,车载终端在物流运输、公共交通等领域得到广泛应用。车载终端以其强大的功能,为不同行业提供定制化的解决方案。本文将盘点车载终端的核心功能,并给出工业场景的应用案例。 一、车载终端SV900的核心功能 1. 车辆定位 车载终端集成高灵敏度的GPS模块,…

鉴源论坛 · 观模丨软件单元测试真的有必要吗?(下)

作者 | 包丹珠 上海控安产品总监 版块 | 鉴源论坛 观模 社群 | 添加微信号“TICPShanghai”加入“上海控安51fusa安全社区” “软件单元测试真的有必要吗&#xff1f;&#xff08;上&#xff09;”一文中&#xff0c;着重探讨了单元测试的重要性及其正面临的困境&#xff0c…

StoneDB顺利通过中科院软件所 2023 开源之夏 结项审核

近日&#xff0c;中科院软件所-开源软件供应链点亮计划-开源之夏2023的结项名单正式出炉&#xff0c;经过三个月的项目开发和一个多月的严格审核&#xff0c;共产生 418个成功结项项目&#xff01;其中&#xff0c;StoneDB 作为本次参与开源社区&#xff0c;社区入选的两个项目…

<shell>《Shell脚本-极简实用手册(高级)》 (自用、持续更新)

1 变量 1.1 2>&1 解释&#xff1a;将“标准错误”输出到“标准输出文件中”。 示例&#xff1a;cat /etc/hosts >> $LOG 2>&1 说明&#xff1a; 1、使用 > 或 >> 时&#xff0c;默认为标准输出 1 重定向, 所以 > file 就是 1> file 的省…

EtherCAT超高速实时运动控制卡XPCIE1032H上位机C#开发(二):EtherCAT总线初始化

XPCIE1032H功能简介 XPCIE1032H是一款基于PCI Express的EtherCAT总线运动控制卡&#xff0c;可选6-64轴运动控制&#xff0c;支持多路高速数字输入输出&#xff0c;可轻松实现多轴同步控制和高速数据传输。 XPCIE1032H集成了强大的运动控制功能&#xff0c;结合MotionRT7运动…

ADI 阻抗测量开发板AD5940调试

硬件环境&#xff1a; 评估板A,阻抗测试板 EVAL-AD5940BIOZ&#xff0c;阻抗测试板信息链接如下&#xff1a; https://wiki.analog.com/resources/eval/user-guides/eval-ad5940/hardware/eval-ad5940bioz 评估板B,MCU控制板 EVAL-ADICUP3029&#xff0c;控制板信息链接如下…

Matlab绘制双坐标轴图示例函数yyaxis

一、前言 出于一些需求&#xff0c;我们需要将两个不同属性的参量绘制在同一张图上&#xff0c;但是两个参量属性不同&#xff0c;即单位不同&#xff0c;纵坐标值分布范围不同&#xff0c;此刻&#xff0c;我们只需要将一个参量的值在y轴左侧展示&#xff0c;另一个参量的值在…

【案例】可视化大屏

人狠话不多,直接上效果图 这里放的地图自己去实现吧,如果也想实现3D地球话,等笔者那天有心情写篇文章; 说明:script中methods部分代码是没用,可以直接删掉,根据个人情况去写, 内容:笔者也就对页面布局进行了设计,内容的填充就靠个人了 <template><div :sty…

linux使用chage修改用户密码过期时间解决rac安装互信问题

文章目录 一、RAC建多实例库提示互信问题二、原因分析1.修改系统用户密码期限2.修改语法&#xff1a;chage [选项] 用户名3.常用示例&#xff1a; 一、RAC建多实例库提示互信问题 二、原因分析 因为此次是在原有集群情况下创建多个实例&#xff0c;其实不需要优先排查俩节点的…