在vue中为了安全,默认情况是获取不到 navigator.userAgent
对象属性的,获取的是一个undefind值,这个是很重要的一个信息。在经历无数次百度,看到网上比较多的就是,vue环境中有两种方式可以实现摄像头拍照功能。
第一种方式:开启 https
环境
第二种方式:配置浏览器的目标位置 --unsafely-treat-insecure-origin-as-secure="http://localhost:8080/"
好,下面我们会详细讲解下这两种方式怎么使用
如果你要使用 https
方式的话,就是说后端的接口方式之前的http形式的要全部已https方式了。那么首先你需要去网站备案。比较复杂,而且需要一系列的前后端鉴权配置。才能让你的项目是https环境。
但是,如果后端现在没有https环境给你去做开发的话,那么前端在vue中可以模拟使用https
形式去跑项目。缺点就是后端的http
的接口,在https中不不能使用。
3.1 vue中 开启 https
在 package.json
中 配置运行方式 "dev": "vue-cli-service serve --https"
3.2 然后 npm run dev 运行项目发现可以看到是以 https运行的项目。
推荐使用的是这种方式,这种方式可以避免使用https
去认证的过程,也可以使用http
去调用项目的接口。并且在本地开发环境和现上环境不会出现问题。`只需要浏览器配置目标位置后重新打开浏览器即可
4.1 浏览器配置 --unsafely-treat-insecure-origin-as-secure="http://localhost:8080/"
右键属性,配置目标位置,注意localhost:8080 就是你项目启动的ip和端口,这里不在过多阐述。
这个是我的目标里面的路径,如果配置不成功可以参考(--unsafely-treat-insecure-origin-as-secure
前面是有一个空格的)
“C:\Program Files (x86)\Google\Chrome\Application\chrome.exe” --unsafely-treat-insecure-origin-as-secure=“http://localhost:8080/”
4.2 判断是否设置成功
设置后一定要重新打开浏览器,看下是否存在这样的提示,如果有,说明设置成功了。
好了下面我们可以进行拍照了。
上面两种方式,代码都是一样,只是第一种是使用https才能获取 navigator.userAgent
对象。
第二种是通过设置浏览器的目标路径后获取的 navigator.userAgent
对象
Photograph.vue
封装<template>
<div id="app">
<div class="content"> <span style="color:red">base64数据:span>{
{image}}div>
<Photograph :image="image" :statusInfo="statusInfo" @getPhoto="getPhoto">Photograph>
div>
template>
<script>
<template>
<div id="Photograph">
<div class="ptoContainer">
<video id="video" class="video" width="320" autoplay="autoplay"></video>
<div
:style="{backgroundImage: `url(${image})`}"
class="headImage"
v-if="image"
v-show="!cameraStatus"
></div>
<!-- 图片获取状态 -->
<div class="photoViewStatus" v-show="photoAlertStatus || statusInfo.status !== ''">
<div class="Loading">
<img
src="./loading.png"
class="loader"
v-show="statusInfo.status === 'loading'"
/>
<img
src="./success.png"
class="loaderNoAni"
v-show="statusInfo.status === 'success'"
/>
</div>
<p>{
{
statusInfo.msg}}</p>
</div>
</div>
<div class="btnBox">
<!-- 拍照按钮 -->
<button class="btn" v-if="!cameraStatus" @click="connectCameraFn">拍照</button>
<button class="btn" v-else @click="takePhotoFn">确认</button>
</div>
</div>
</template>
<script>
import MyLib from "@/lib/index";
export default {
name: "",
props: {
image: {
type: String,
default: ""
},
statusInfo: {
type: Object,
default: {
status: "", // loading | success
msg: ""
}
}
},
data() {
return {
cameraStatus: false, // 拍照状态, true => 开启;false => 关闭
photo: "",
photoAlertStatus: false, // 图像提示文案显示状态 true => 显示;false => 隐藏
getStatus: true // true => loading状态, false => 失败状态
};
},
computed: {
// 浏览器类型/版本(控制摄像头video区域大小),在部分浏览器获取的摄像头拍照区域为长方形,所以需要判断浏览器,当前低版本的 safari 和 uc 会是长方形区域
systemCameraVideo() {
let system = MyLib.judgeBrowser();
let v = parseInt(system.version.replace(/\./g, ""));
if (
system.browser === "chrome" ||
(system.browser === "safari" && v >= 1211)
) {
return true;
}
return false;
}
},
methods: {
// 连接摄像头
connectCameraFn() {
this.photoAlertStatus = false; // 关闭提示框
// 区域控制
let obj = {
};
if (this.systemCameraVideo) {
obj = {
width: 320, height: 320 };
} else {
obj = {
width: 320 };
}
// end
let constraints = {
video: obj,
audio: false
};
const video = document.getElementById("video");
// 当前在IE浏览器无法调用摄像头
try {
let Promise = navigator.mediaDevices.getUserMedia(constraints);
Promise.then(MediaStream => {
video.srcObject = MediaStream;
window.MediaStreamTrack = MediaStream.getTracks()[0]; // 摄像头对象
video.play();
this.cameraStatus = true;
});
} catch (err) {
this.$toast(
"浏览器不支持调用摄像头,请更换最新的谷歌浏览器,或者其他最新版",
3000,
"upFade"
);
}
},
// 绘制照片
takePhotoFn() {
let video = document.getElementById("video");
let canvas = document.createElement("canvas");
canvas.width = canvas.height = 320;
let ctx = canvas.getContext("2d");
let w = video.offsetWidth;
let h = video.offsetHeight;
let y = (canvas.width - h) / 2;
// 区域控制
if (this.systemCameraVideo) {
y = 0;
}
// end
ctx.drawImage(video, 0, y, w, h);
let base64 = canvas.toDataURL("image/jpeg", 0.4);
this.photo = base64;
// base64 => FormData
let Blob = MyLib.convertBase64UrlToBlob(base64);
let formData = new FormData();
formData.append("file", Blob);
this.$emit("getPhoto", {
formData: this.photo, base64: base64 });
console.log(base64);
// 关闭
this.cameraStatus = false; // 修改摄像头启动状态
window.MediaStreamTrack &&
window.MediaStreamTrack.stop &&
window.MediaStreamTrack.stop(); // 关闭摄像头
this.deviceInfoStatus = false;
// end
}
}
};
script>
<style scoped>
// 省略
style>
主要是转换为base64
方法和navigator.userAgent
兼容判断
const myLib = {
// base64转blob
convertBase64UrlToBlob(urlData) {
let arr = urlData.split(',');
let mime = arr[0].match(/:(.*?);/)[1];
let bstr = atob(arr[1]);
let n = bstr.length;
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {
type: mime });
},
// 浏览器类型判断及版本
judgeBrowser() {
// 获取IE浏览器版本
function getIeVersion() {
let IEMode = document.documentMode;
let rMsie = /(msie\s|trident.*rv:)([\w.]+)/;
let ma = navigator.userAgent.toLowerCase();
let match = rMsie.exec(ma);
try {
return match[2];
} catch (e) {
return IEMode;
}
}
let System = {
};
let ua = navigator.userAgent.toLowerCase();
if (ua.match(/msie/) != null || ua.match(/trident/) != null) {
System.browser = 'IE'
System.version = getIeVersion()
} else if (ua.indexOf('ubrowser') > -1) {
System.browser = 'uc';
System.version = '';
} else {
let re = /(msie|firefox|chrome|opera|version).*?([\d.]+)/;
let m = ua.match(re);
System.browser = m[1].replace(/version/, "safari");
System.version = m[2];
}
return System;
}
};
export default myLib;
Photograph.vue
使用<template>
<div id="app">
<div class="content"> <span style="color:red">base64数据:span>{
{image}}div>
<Photograph :image="image" :statusInfo="statusInfo" @getPhoto="getPhoto">Photograph>
div>
template>
<script>
import Photograph from "./plugs/camera";
export default {
name: "App",
components: {
Photograph
},
data() {
return {
image: "", // 传递图像数据
statusInfo: {
// 状态显示
status: "", // loading | fail
msg: ""
}
};
},
mounted() {
},
methods: {
// 获取拍照图像
getPhoto({
formdata, base64 }) {
// 上传中
this.statusInfo.status = "loading";
this.statusInfo.msg = "上传中";
// 上传失败
setTimeout(() => {
this.statusInfo.status = "success";
this.statusInfo.msg = "成功";
}, 2000);
// 上传成功
setTimeout(() => {
this.statusInfo.status = "";
this.statusInfo.msg = "";
this.image = base64;
}, 4000);
}
}
};
script>
如果对你有帮助,麻烦点个