vue2 调用摄像头pc端获取摄像头权限拍照
效果图如下:
html结构
在这里插入代码片
上传按钮
在这里插入代码片
<div @click="photoUploadHandle">
<i
class="el-icon-camera-solid"
style="color: #d7dbec; font-size: 22px"
></i>
<span class="put">点击上传</span>
</div>
<el-dialog
:visible.sync="dialogVisible"
width="50%"
:before-close="handleClose"
>
<div slot="title" class="titleTab">
<div
:class="activeName == 1 ? 'active' : 'inActive'"
@click="tabChange(1)"
>
摄像头抓拍
</div>
<div
:class="activeName == 2 ? 'active' : 'inActive'"
@click="tabChange(2)"
>
本地上传
</div>
</div>
<div class="contentTab">
<div class="photo" v-if="activeName == 1">
<div class="photo-top">
<div class="left">
<video
style="width: 100%"
id="videoCamera"
class="canvas"
:width="videoWidth"
:height="videoHeight"
autoPlay
></video>
<div style="text-align: center; padding-top: 20px">
<el-button type="primary" @click="photographBtn" size="small"
>确定</el-button
>
</div>
</div>
<div class="right">
<div class="example">
<img src="../../../../assets/images/face.png" alt="" />
</div>
<div class="exampleTwo">
<canvas
id="canvasCamera"
class="canvas"
:width="125"
:height="160"
></canvas>
<canvas
style="display: none"
id="canvasCamera1"
class="canvas"
:width="330"
:height="420"
></canvas>
</div>
</div>
</div>
<div class="desc">
<span>注意事项:</span>
<span>1.图像大小建议尺寸为220*280像素:</span>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="handleClose">取 消</el-button>
<el-button type="primary" @click="submitHandle">确 定</el-button>
</span>
</div>
<div class="photo" v-if="activeName == 2">
<div class="photo-top">
<div class="left">
<div class="uploadFlex">
<el-upload
class="upload-demo"
drag
action=""
:on-change="getFile"
:limit="1"
:auto-upload="false"
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">
将文件拖到此处,或点击上传<em>点击上传</em>
</div>
</el-upload>
</div>
</div>
<div class="right">
<div class="example">
<img src="../../../../assets/images/face.png" alt="" />
</div>
<div class="exampleTwo">
<img
:src="
imgSrc
? imgSrc
: require('../../../../assets/images/face.png')
"
width="125"
height="160"
alt=""
/>
</div>
</div>
</div>
<div class="desc">
<span>注意事项:</span>
<span>1.图像大小建议尺寸为220*280像素:</span>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="handleClose">取 消</el-button>
<el-button type="primary" @click="handleSubmit">确 定</el-button>
</span>
</div>
</div>
</el-dialog>
话不多说 上代码:
data中定义变量
``export default{
data(){
return{
os: true, //控制摄像头开关
thisVideo: null,
thisContext: null,
thisCancas: null,
imgSrc: “”,
activeName:‘1’ //弹窗的标题栏高亮
videoWidth: 544,
videoHeight: 418,
dialogVisible:false,//弹窗的显隐
}
}
}
在这里插入代码片
```// 点击图片上传弹窗显示
photoUploadHandle() {
this.activeName = 1;
this.dialogVisible = true;
this.$nextTick(() => {
this.resetBtn();
this.openCamera();
});
},
// 调用摄像头权限
openCamera() {
console.log("调取权限");
//必须在model中render后才可获取到dom节点,直接获取无法获取到model中的dom节点
this.$nextTick(() => {
const _this = this;
this.os = false; //切换成关闭摄像头
this.thisCancas = document.getElementById("canvasCamera");
this.thisCancas1 = document.getElementById("canvasCamera1");
this.thisContext = this.thisCancas.getContext("2d");
this.thisContext1 = this.thisCancas1.getContext("2d");
this.thisVideo = document.getElementById("videoCamera");
// 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象
if (navigator.mediaDevices === undefined) {
navigator.mediaDevices = {};
}
// 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象
// 使用getUserMedia,因为它会覆盖现有的属性。
// 这里,如果缺少getUserMedia属性,就添加它。
if (navigator.mediaDevices.getUserMedia === undefined) {
navigator.mediaDevices.getUserMedia = function (constraints) {
// 首先获取现存的getUserMedia(如果存在)
let getUserMedia =
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.getUserMedia;
// 有些浏览器不支持,会返回错误信息
// 保持接口一致
if (!getUserMedia) {
return Promise.reject(
new Error("getUserMedia is not implemented in this browser")
);
}
// 否则,使用Promise将调用包装到旧的navigator.getUserMedia
return new Promise(function (resolve, reject) {
getUserMedia.call(navigator, constraints, resolve, reject);
});
};
}
const constraints = {
audio: false,
video: {
width: 220, // _this.videoWidth,
height: 280, // _this.videoHeight,
transform: "scaleX(-1)",
},
};
navigator.mediaDevices
.getUserMedia(constraints)
.then(function (stream) {
// 旧的浏览器可能没有srcObject
if ("srcObject" in _this.thisVideo) {
_this.thisVideo.srcObject = stream;
} else {
// 避免在新的浏览器中使用它,因为它正在被弃用。
_this.thisVideo.src = window.URL.createObjectURL(stream);
}
_this.thisVideo.onloadedmetadata = function (e) {
_this.thisVideo.play();
};
})
.catch((err) => {
this.$message({
message: "没有开启摄像头权限或浏览器版本不兼容",
type: "warning",
});
});
});
},
// 拍照按钮
photographBtn() {
// 点击,canvas画图
this.thisContext.drawImage(this.thisVideo, 0, 0, 125, 160);
// 获取图片base64链接预览
this.imgSrc = this.thisCancas.toDataURL("image/jpeg");
},
// 清空画布
clearCanvas(id) {
let c = document.getElementById(id);
let cxt = c.getContext("2d");
cxt.clearRect(0, 0, c.width, c.height);
},
// 重置画布
resetBtn() {
this.clearCanvas("canvasCamera");
},
// 关闭摄像头
stopCamera() {
if (this.thisVideo && this.thisVideo !== null) {
this.thisVideo.srcObject.getTracks()[0].stop();
this.os = true; //切换成打开摄像头
}
},
//关闭弹窗
handleClose() {
this.dialogVisible = false;
if (this.activeName == 1) {
this.activeName = 2;
this.resetBtn();
this.stopCamera();
this.os = false;
this.dialogVisible = false;
} else {
this.stopCamera();
this.dialogVisible = false;
}
},
//点击 本地上传确定
handleSubmit() {
this.dialogVisible = false;
this.form.face = this.imgSrc;
},
//点击 摄像头上传确定
submitHandle() {
this.dialogVisible = false;
this.form.face = this.imgSubSrc;
},
// 上传图片转base64
getFile(file, fileList) {
this.getBase64(file.raw).then((res) => {
this.imgSrc = res;
});
},
getBase64(file) {
let that = this;
return new Promise(function (resolve, reject) {
// 创建一个img对象
var img = new Image();
let reader = new FileReader();
let imgResult = "";
reader.readAsDataURL(file);
reader.onload = function (e) {
img.src = e.target.result;
img.onload = function () {
// 缩放图片需要canvas(也可以在DOM中直接定义canvas标签,这样就能把压缩完的图片不转base64也能直接显示出来)
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
// 图片原始尺寸
var originWidth = this.width;
var originHeight = this.height;
// 最大尺寸限制,可通过设置宽高来实现图片压缩程度
// var maxWidth = 220,
// maxHeight = 280;
// 目标尺寸
var targetWidth = originWidth;
var targetHeight = originHeight;
// 图片尺寸超过最大尺寸限制
// if (originWidth > maxWidth || originHeight > maxHeight) {
// if (originWidth / originHeight > maxWidth / maxHeight) {
// // 更改宽度,按照宽度限定尺寸
// targetWidth = maxWidth;
// targetHeight = Math.round(
// maxWidth * (originHeight / originWidth)
// );
// } else {
// targetHeight = maxHeight;
// targetWidth = Math.round(
// maxHeight * (originWidth / originHeight)
// );
// }
// }
// 对图片进行缩放
canvas.width = targetWidth;
canvas.height = targetHeight;
// 清除画布
context.clearRect(0, 0, targetWidth, targetHeight);
/** 图片压缩
* 第一个参数是创建的img对象
* 第二三个参数是左上角坐标
* 后两个参数是画布区域宽高
*/
console.log(
targetWidth,
targetHeight,
" targetWidth, targetHeight"
);
context.drawImage(img, 0, 0, targetWidth, targetHeight);
/** 压缩后的base64文件
* 第一个参数可以为image/jpeg或image/webp类型的图片
* 第二个参数设置图片质量取值0-1,超出则以默认值0.92替代
*/
that.imgSrc = canvas.toDataURL("image/jpeg", 1);
};
// imgResult = reader.result;
};
reader.onerror = function (error) {
reject(error);
};
reader.onloadend = function () {
resolve(imgResult);
};
});
},