前言:
本文将介绍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); });
实现效果: