vue+elementUI实现调用PC摄像头拍照上传图片(谷歌火狐测试可用,其他自测)
生活随笔
收集整理的這篇文章主要介紹了
vue+elementUI实现调用PC摄像头拍照上传图片(谷歌火狐测试可用,其他自测)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
一定部署到https域名上,否則無法調(diào)用攝像頭權(quán)限!!!
效果圖
定義Data
data () {return {dialogTableVisible:false,videoWidth: 500,videoHeight: 400,imgSrc: '',thisCancas: null,thisContext: null,thisVideo: null,ImgFile:'',//返回的圖片文件}}, 調(diào)用攝像頭權(quán)限 getCompetence () {this.$nextTick(function () {var _this = this;this.thisCancas = document.getElementById('canvasCamera');this.thisContext = this.thisCancas.getContext('2d');this.thisVideo = document.getElementById('videoCamera');// 舊版本瀏覽器可能根本不支持mediaDevices,我們首先設(shè)置一個(gè)空對(duì)象if (navigator.mediaDevices === undefined) {navigator.mediaDevices = {}}// 一些瀏覽器實(shí)現(xiàn)了部分mediaDevices,我們不能只分配一個(gè)對(duì)象// 使用getUserMedia,因?yàn)樗鼤?huì)覆蓋現(xiàn)有的屬性。// 這里,如果缺少getUserMedia屬性,就添加它。if (navigator.mediaDevices.getUserMedia === undefined) {navigator.mediaDevices.getUserMedia = function (constraints) {// 首先獲取現(xiàn)存的getUserMedia(如果存在)var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia;// 有些瀏覽器不支持,會(huì)返回錯(cuò)誤信息// 保持接口一致if (!getUserMedia) {return Promise.reject(new Error('getUserMedia is not implemented in this browser'))}// 否則,使用Promise將調(diào)用包裝到舊的navigator.getUserMediareturn new Promise(function (resolve, reject) {getUserMedia.call(navigator, constraints, resolve, reject)})}}var constraints = { audio: false, video: { width: this.videoWidth, height: this.videoHeight, transform: 'scaleX(-1)' } };navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {// 舊的瀏覽器可能沒有srcObjectif ('srcObject' in _this.thisVideo) {_this.thisVideo.srcObject = stream} else {// 避免在新的瀏覽器中使用它,因?yàn)樗诒粭売谩this.thisVideo.src = window.URL.createObjectURL(stream)}_this.thisVideo.onloadedmetadata = function (e) {_this.thisVideo.play()}}).catch(err => {console.log(err)})});},繪制圖片,生成一個(gè)base64文件
setImage(){var _this = this;// 點(diǎn)擊,canvas畫圖_this.thisContext.drawImage(_this.thisVideo, 0, 0, _this.videoWidth, _this.videoHeight);// 獲取圖片base64鏈接var image = this.thisCancas.toDataURL('image/png');_this.imgSrc = image;},base64文件轉(zhuǎn)文件流
dataURLtoFile (dataurl, filename) {var arr = dataurl.split(',');var mime = arr[0].match(/:(.*?);/)[1];var bstr = atob(arr[1]);var n = bstr.length;var u8arr = new Uint8Array(n);while (n--) {u8arr[n] = bstr.charCodeAt(n)}return new File([u8arr], filename, { type: mime })},上傳文件流至后臺(tái)(form提交)
handleUpdata(){//已form提交if (this.imgSrc!==''){let file = this.imgSrc; // 把整個(gè)base64給filelet type = "image/jpeg"; // 定義圖片類型(canvas轉(zhuǎn)的圖片一般都是png,也可以指定其他類型)let time=(new Date()).valueOf();//生成時(shí)間戳let name = time + ".jpg"; // 定義文件名字(例如:abc.png , cover.png)let conversions = this.dataURLtoFile(file, name); // 調(diào)用base64轉(zhuǎn)圖片方法let parms=new FormData();parms.append('file',conversions);let url='*********';//你的接口this.axios.post(url,parms,{headers: {'Content-Type': 'multipart/form-data'}}).then(res=>{console.log(res);this.ImgFile=res.data;}).catch(err=>{this.$notify.error({title: '上傳失敗',message: err.msg});})}},關(guān)閉攝像頭
stopNavigator () {this.thisVideo.srcObject.getTracks()[0].stop()}, ?離開頁面時(shí)關(guān)閉攝像頭
beforeDestroy () {this.stopNavigator()}附上源碼:
<template><div><el-button@click="onTake"icon="el-icon-camera"size="small">拍照上傳</el-button><el-dialogtitle="拍照上傳":visible.sync="visible"@close="onCancel"width="1065px"><div class="box"><video id="videoCamera" class="canvas" :width="videoWidth" :height="videoHeight" autoPlay></video><canvas id="canvasCamera" class="canvas" :width="videoWidth" :height="videoHeight"></canvas></div><div slot="footer"><el-button@click="drawImage"icon="el-icon-camera"size="small">拍照</el-button><el-buttonv-if="open"@click="getCompetence"icon="el-icon-video-camera"size="small">打開攝像頭</el-button><el-buttonv-else@click="stopNavigator"icon="el-icon-switch-button"size="small">關(guān)閉攝像頭</el-button><el-button@click="resetCanvas"icon="el-icon-refresh"size="small">重置</el-button><el-button@click="onCancel"icon="el-icon-circle-close"size="small">取消</el-button><el-button@click="onUpload":loading="loading"type="primary"icon="el-icon-upload2"size="small">上傳</el-button></div></el-dialog></div> </template><script>//拍照上傳組件//父組件通過函數(shù) getImg 獲取照片路徑,如 @getImg="getImg"const Address = require('../utils/url');//圖片上傳地址export default {name: "TakePhotos",data() {return {imgSrc: "",visible: false,//彈窗l(fā)oading: false,//上傳按鈕加載open: false,//控制攝像頭開關(guān)thisVideo: null,thisContext: null,thisCancas: null,videoWidth: 500,videoHeight: 400}},methods: {onTake() {this.visible = true;this.getCompetence();},onCancel() {this.visible = false;this.resetCanvas();this.stopNavigator();},//base64轉(zhuǎn)成文件后上傳onUpload() {if (this.imgSrc) {const file = this.imgSrc; // 把整個(gè)base64給fileconst time = (new Date()).valueOf();//生成時(shí)間戳const name = time + ".png"; // 定義文件名字(例如:abc.png , cover.png)const conversions = this.dataURLtoFile(file, name); // 調(diào)用base64轉(zhuǎn)圖片方法const data = new FormData();data.append('file', conversions);const options = {method: "POST", //請(qǐng)求方法body: data, //請(qǐng)求體headers: {'Accept': 'application/json'},};this.loading = true;fetch(Address.UPLOAD, options).then((response) => {return response.json();}).then((responseText) => {this.loading = false;if (responseText.code === 0) {this.imgSrc = responseText.data.src;this.$emit('getImg', responseText.data.src);//傳遞給父組件this.onCancel();this.$notify({title: '上傳成功',message: responseText.msg,type: 'success'});}}).catch((error) => {this.loading = false;this.$notify.error({title: '上傳失敗',message: error.msg,});})}else {this.$notify({title: '警告',message: '請(qǐng)點(diǎn)擊拍照',type: 'warning'});}},// 調(diào)用攝像頭權(quán)限getCompetence() {//必須在model中render后才可獲取到dom節(jié)點(diǎn),直接獲取無法獲取到model中的dom節(jié)點(diǎn)this.$nextTick(() => {const _this = this;this.open = false;//切換成關(guān)閉攝像頭this.thisCancas = document.getElementById('canvasCamera');this.thisContext = this.thisCancas.getContext('2d');this.thisVideo = document.getElementById('videoCamera');// 舊版本瀏覽器可能根本不支持mediaDevices,我們首先設(shè)置一個(gè)空對(duì)象if (navigator.mediaDevices === undefined) {navigator.mediaDevices = {}}// 一些瀏覽器實(shí)現(xiàn)了部分mediaDevices,我們不能只分配一個(gè)對(duì)象// 使用getUserMedia,因?yàn)樗鼤?huì)覆蓋現(xiàn)有的屬性。// 這里,如果缺少getUserMedia屬性,就添加它。if (navigator.mediaDevices.getUserMedia === undefined) {navigator.mediaDevices.getUserMedia = function (constraints) {// 首先獲取現(xiàn)存的getUserMedia(如果存在)let getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia;// 有些瀏覽器不支持,會(huì)返回錯(cuò)誤信息// 保持接口一致if (!getUserMedia) {return Promise.reject(new Error('getUserMedia is not implemented in this browser'))}// 否則,使用Promise將調(diào)用包裝到舊的navigator.getUserMediareturn new Promise(function (resolve, reject) {getUserMedia.call(navigator, constraints, resolve, reject)})}}const constraints = {audio: false,video: {width: _this.videoWidth, height: _this.videoHeight, transform: 'scaleX(-1)'}};navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {// 舊的瀏覽器可能沒有srcObjectif ('srcObject' in _this.thisVideo) {_this.thisVideo.srcObject = stream} else {// 避免在新的瀏覽器中使用它,因?yàn)樗诒粭売谩this.thisVideo.src = window.URL.createObjectURL(stream)}_this.thisVideo.onloadedmetadata = function (e) {_this.thisVideo.play()}}).catch(err => {this.$notify({title: '警告',message: '沒有開啟攝像頭權(quán)限或?yàn)g覽器版本不兼容.',type: 'warning'});});});},//繪制圖片drawImage() {// 點(diǎn)擊,canvas畫圖this.thisContext.drawImage(this.thisVideo, 0, 0, this.videoWidth, this.videoHeight);// 獲取圖片base64鏈接this.imgSrc = this.thisCancas.toDataURL('image/png');},//base64轉(zhuǎn)文件dataURLtoFile(dataurl, filename) {let arr = dataurl.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 File([u8arr], filename, {type: mime})},//清空畫布clearCanvas(id) {let c = document.getElementById(id);let cxt = c.getContext("2d");cxt.clearRect(0, 0, c.width, c.height);},//重置畫布resetCanvas() {this.imgSrc = "";this.clearCanvas('canvasCamera');},//關(guān)閉攝像頭stopNavigator() {if (this.thisVideo && this.thisVideo !== null) {this.thisVideo.srcObject.getTracks()[0].stop();this.open = true;//切換成打開攝像頭}},},beforeDestroy() {this.stopNavigator()}} </script><style scoped>.box {display: flex;justify-content: space-between;}.canvas {border: 1px solid #e8e8e8;} </style>?
總結(jié)
以上是生活随笔為你收集整理的vue+elementUI实现调用PC摄像头拍照上传图片(谷歌火狐测试可用,其他自测)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2008年“TI杯”湖北省大学生电子设计
- 下一篇: 积加ERP与金蝶云星空对接集成出入库记录