<!-- 父组件 -->
<!-- 调用摄像头必须使用https域名才能调同 -->
<div style="width: 0; height: 0; overflow: hidden">
<videoCamera width="100px" height="100px" ref="cVideoCameraRef" />
</div>
<button @click="getImage">拍照</button>
methods:{
getImage() {
this.$refs.cVideoCameraRef.getImage().then((res) => {
console.log(res);
});
},
}
<!-- 子组件 -->
<template>
<div class="c-video-camera" :style="`width: ${width};height: ${height};`">
<!-- Video -->
<video ref="videoCameraRef" class="c-video_video" autoplay></video>
<!-- Loading -->
<div v-if="loading" class="c-video_mask">
<div class="c-video_loading"></div>
</div>
<!-- Error -->
<div v-if="error" class="c-video_mask">
<div class="c-video_error">
<!-- <img class="c-video-error--icon" src="./error.png" alt="error" /> -->
<div class="c-video-error--msg">
{{ errMsg }} <span @click="openCamera">重新加载</span>
</div>
</div>
</div>
</div>
</template>
<script>
const msgTypes = {
devicesnotfounderror: "未检测到摄像头",
"could not start video source": "无法访问到摄像头",
"requested device not found": "未检测到摄像头",
"permission denied": "浏览器禁止本页面使用摄像头,请开启使用摄像头权限",
"getUserMedia is not implemented in this browser":
"浏览器不支持访问用户媒体设备,请升级或更换浏览器",
};
// uniapp开发移动端人脸抓拍
export default {
name: "VideoCamera",
props: {
width: {
type: String,
default: "100%",
},
height: {
type: String,
default: "100%",
},
},
data() {
return {
videoCameraRef: null,
loading: false,
error: false,
errMsg: "",
deviceId: "",
deviceName: "",
stream: null,
};
},
methods: {
getErrorMessage(err) {
const message = err.message || err.name || err || "";
return msgTypes[message.toLowerCase()] || "未检测到摄像头";
},
// 初始化摄像头
init() {
if (!navigator.mediaDevices) {
this.errMsg = this.getErrorMessage("requested device not found");
return setTimeout(() => {
this.error = true;
this.$emit("error", this.errMsg);
}, 500);
}
navigator.mediaDevices.addEventListener("devicechange", () => {
this.openCamera();
});
this.openCamera();
},
openCamera() {
this.error = false;
this.loading = true;
if (!navigator.mediaDevices) {
this.errMsg = this.getErrorMessage("requested device not found");
return setTimeout(() => {
this.loading = false;
this.error = true;
this.$emit("error", this.errMsg);
}, 500);
}
navigator.mediaDevices.enumerateDevices().then((devices) => {
const videoDevices = devices.filter(
(item) => item.kind == "videoinput"
);
if (!videoDevices || videoDevices.length == 0) {
this.errMsg = this.getErrorMessage("requested device not found");
this.loading = false;
this.error = true;
return this.$emit("error", this.errMsg);
}
this.deviceId = videoDevices[0].deviceId;
this.deviceName = videoDevices[0].label;
this.getStream();
});
this.loading = false;
},
closeCamera() {
if (this.stream) {
this.stream.getVideoTracks().forEach((track) => {
track.stop();
});
}
},
getStream() {
const constraints = {
audio: false,
video: {
facingMode: "user",
},
};
navigator.mediaDevices
.getUserMedia(constraints)
.then(function (stream) {
let video = document.querySelector("video");
video.srcObject = stream;
video.play();
})
.catch(function (err) {
console.error("Error getting video:", err);
});
},
// 拍照 截屏
getImage() {
return new Promise((resolve, reject) => {
if (this.loading || this.error) {
reject();
} else {
const canvas = document.createElement("canvas");
const w =
this.$refs.videoCameraRef.$el.children[0].childNodes[0].offsetWidth;
const h =
this.$refs.videoCameraRef.$el.children[0].childNodes[0]
.offsetHeight;
canvas.width = w;
canvas.height = h;
const ctx = canvas.getContext("2d");
ctx.drawImage(
this.$refs.videoCameraRef.$el.children[0].childNodes[0],
0,
0,
w,
h
);
const image = canvas.toDataURL("image/jpeg", 0.5);
// const image = canvas.toDataURL('image/jpeg', 0.5).replace('data:image/jpeg;base64,', '')
resolve(image);
}
});
},
},
mounted() {
this.videoCameraRef = this.$refs.videoCameraRef;
this.init();
},
beforeDestroy() {
this.closeCamera();
},
};
</script>
<style lang="scss" scope>
.c-video-camera {
background-color: #000000;
position: relative;
.c-video_video {
width: 100%;
height: 100%;
display: block;
}
.c-video_mask {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: center;
}
.c-video_loading {
width: 30px;
height: 30px;
border: 2px solid #ffffff;
border-top-color: transparent;
border-radius: 100%;
animation: circle infinite 0.75s linear;
}
.c-video_error {
.c-video-error--icon {
width: 32px;
height: 32px;
display: block;
margin: 0 auto;
}
.c-video-error--msg {
// margin-top: 15px;
color: #ffffff;
font-size: 14px;
text-align: center;
span {
text-decoration: underline;
cursor: pointer;
}
}
}
// 转转转动画
@keyframes circle {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
}
</style>
uniapp开发移动端人脸抓拍
最新推荐文章于 2025-02-07 15:07:41 发布