目录
前言:
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);
});