1.子组件(高拍仪的拍照和上传服务器)
<template>
<div class="photoClass">
<div class="upPhotoClass" @click="upPhotoFn" />
<el-dialog :visible.sync="dialogVisible" :modal="false" width="30%" :show-close="false">
<canvas v-show="false" ref="canvas" width="400" height="400" />
<video ref="video" width="400" height="400" autoplay />
<span slot="footer" class="dialog-footer">
<el-button @click="handleClose">取 消</el-button>
<el-button type="primary" @click="photograph">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { apiUpload } from '@/api/index.js'
export default {
props: {
edits: {
type: Boolean,
default: true
}
},
data() {
return {
dialogVisible: false,
camera: '',
imgSrc: ''
}
},
computed: {},
methods: {
//点击弹出高拍仪摄像头
upPhotoFn() {
if (!this.edits) {//是否可以点开dialog
return
}
this.dialogVisible = true
this.getAllCamera()
},
handleClose() {
this.closeCamera()
this.dialogVisible = false
},
// 获取摄像头
getAllCamera() {
navigator.mediaDevices
.enumerateDevices()
.then(this.gotDevices)
.then(this.callCamera)
.catch(this.handleError)
},
// 选择摄像头
gotDevices(deviceInfos) {
console.log(deviceInfos)
const options = []
for (var i = 0; i < deviceInfos.length; ++i) {
var deviceInfo = deviceInfos[i]
var option = document.createElement('option')
option.value = deviceInfo.deviceId
if (deviceInfo.kind === 'videoinput') {
options.push({
value: deviceInfo.deviceId,
label: deviceInfo.label
})
} else {
// console.log('Found ome other kind of source/device: ', deviceInfo);
}
}
this.camera = options[1].value//options[1]高拍仪第二个摄像头,第一个写为options[0]
},
// 调用摄像头错误
handleError(error) {
this.$message.error(error.name + ': ' + error.message)
},
// 调用摄像头
callCamera() {
// this.getAllCamera();
// H5调用电脑摄像头API
navigator.mediaDevices
.getUserMedia({
// video: true,
video: {
optional: [
{
sourceId: this.camera
}
]
}
})
.then(success => {
// console.log(success);
// 摄像头开启成功
this.$refs['video'].srcObject = success
// 实时拍照效果
this.$refs['video'].play()
})
.catch(error => {
this.$message.error(
'摄像头开启失败,请检查摄像头是否可用并重新打开!'
)
})
},
// 关闭摄像头
closeCamera() {
if (!this.$refs['video'].srcObject) {
this.dialogVisible = false
return
}
const stream = this.$refs['video'].srcObject
const tracks = stream.getTracks()
tracks.forEach(track => {
track.stop()
})
this.$refs['video'].srcObject = null
// this.$emit('closeCamera')
},
//拍照
photograph() {
const ctx = this.$refs['canvas'].getContext('2d')
// 把当前视频帧内容渲染到canvas上
ctx.drawImage(this.$refs['video'], 0, 0, 400, 400)
// 转base64格式、图片格式转换、图片质量压缩
// let imgBase64 = this.$refs['canvas'].toDataURL('image/jpeg', 0.7)
const imgurl = this.$refs['canvas'].toDataURL('image/png')
this.imgSrc = imgurl
console.log(imgurl)
this.onUpload()
},
onUpload() {
const file = this.imgSrc // 把整个base64给file
const time = new Date().valueOf() // 生成时间戳
const name = time + '.png' // 定义文件名字(例如:abc.png , cover.png)
const conversions = this.dataURLtoFile(file, name) // 调用base64转图片方法
const data = new FormData()
data.append('file', conversions)
apiUpload(data).then(res => {//上传到服务
console.log(res)
if (res.code == 200) {
this.$emit('changPhotoFn', res.data)//返回值传给父组件
}
})
.catch((e) => {
console.log(e)
})
this.closeCamera()
this.dialogVisible = false
},
// base64转文件
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 })
}
}
}
</script>
<style scoped>
.photoClass {
width: 120px;
height: 120px;
}
.upPhotoClass {
width: 100%;
height: 100%;
border: 1px dotted #d9d9d9;
}
.photoDialogClass {
/* height: 300px; */
}
</style>
2.父组件