vue中调用摄像头拍照,并把拍照的base64格式转换为file传递后台

本文档详细介绍了在Vue项目中如何利用摄像头拍照,并将照片以file格式上传到后台,获取图片url的过程。包括:1) 打开摄像头;2) 实时显示并手动拍照;3) base64转file格式;4) 图片上传及获取url。代码示例展示了从HTML结构、JS逻辑到CSS样式的完整实现。
摘要由CSDN通过智能技术生成

需求:
在vue项目中使用摄像头拍摄照片传递,进行上传,如果上传成功可以获取到url链接,进行下一步的操作

内容梳理

1、首先进入页面打开摄像头
2、点击手动拍照进行拍摄照片,实时显示拍照效果
3、拿到拍摄的照片(base64格式)转换为 file 格式,上传后台
4、上传成功获取该图片的url链接

<template>
    <div>
		<video id="videoCamera" :width="videoWidth" :height="videoHeight" autoplay></video>
        <canvas style="display:none;" id="canvasCamera" :width="videoWidth" :height="videoHeight"></canvas>
        
		<button plain  @click="setImage()">手动拍照</button>
         <p class="fail_tips">拍照,请正脸面向摄像头</p>
         // 给外面盒子设置宽高,可以限制拍照图片的大小位置范围
         <div class="result_img">
             <img :src="imgSrc" alt class="tx_img" width="100%" />
         </div>
         <p class="res_tips">效果展示</p>
    </div>
</template>

<script>
export default {
    data() {
      return {
        // 视频调用相关数据开始
        videoWidth: 245,
        videoHeight: 326,
        imgSrc: "",
        thisCancas: null,
        thisContext: null,
        thisVideo: null,
        openVideo:false,
        //视频调用相关数据结束
        postVideoImg:'',// 图片上传后获取的url链接
      };
    },
    mounted(){
		// 第一步打开摄像头
        this.getCompetence() //调用摄像头
        
    },
    methods: {
        // 第三步、拍照图转换file格式上传,
        // 第四步、获取图片url链接
        postImg(){
            let formData = new FormData()
            formData.append('file', this.base64ToFile(this.imgSrc,'png'))
            formData.append("flag", "videoImg")// 额外参数
            
			// 对应的后台上传图片接口 === app/StudentVideoController/uploadFile
            this.$axios.post('app/StudentVideoController/uploadFile',formData).then(res => {
                // console.log(res);
                if(res.data.code == '00'){
                    // 图片文件传至后台 == 获取到该图片的url路径
                    this.postVideoImg = res.data.FilePath
                    //获得图片的url后,需要做什么
                    //做的事情......
                }

            }).catch(error => {
              console.log(error);
          })

        },
        
        // 调用权限(打开摄像头功能)
        getCompetence() {
          var _this = this;
          _this.thisCancas = document.getElementById("canvasCamera");
          _this.thisContext = this.thisCancas.getContext("2d");
          _this.thisVideo = document.getElementById("videoCamera");
          _this.thisVideo.style.display = 'block';
          // 获取媒体属性,旧版本浏览器可能不支持mediaDevices,我们首先设置一个空对象
          if (navigator.mediaDevices === undefined) {
            navigator.mediaDevices = {};
          }
          // 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象
          // 使用getUserMedia,因为它会覆盖现有的属性。
          // 这里,如果缺少getUserMedia属性,就添加它。
          if (navigator.mediaDevices.getUserMedia === undefined) {
            navigator.mediaDevices.getUserMedia = function(constraints) {
              // 首先获取现存的getUserMedia(如果存在)
              var 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);
              });
            };
          }
          var constraints = {
            audio: false,
            video: {
              width: this.videoWidth,
              height: 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 => {
              console.log(err);
            });
        },
        //  第二步、绘制图片(拍照功能)
        setImage() {
              var _this = this;
              // canvas画图
              _this.thisContext.drawImage(
                _this.thisVideo,
                0,
                0,
              );
              // 获取图片base64链接
              var image = this.thisCancas.toDataURL("image/png");
              _this.imgSrc = image;//赋值并预览图片
              
			//这里是调用上传图片接口===== 
             this.postImg() // 绘制完图片调用图片上传接口
            
        },
        // 关闭摄像头
        stopNavigator() {
            this.thisVideo.srcObject.getTracks()[0].stop();
        },

        // base64 转为 file 
        base64ToFile(urlData, fileName) {
            let arr = urlData.split(',');
            let mime = arr[0].match(/:(.*?);/)[1];
            let bytes = atob(arr[1]); // 解码base64
            let n = bytes.length
            let ia = new Uint8Array(n);
            while (n--) {
                ia[n] = bytes.charCodeAt(n);
            }
            return new File([ia], fileName, { type: mime });
        },
    },
    destroyed: function () { // 离开当前页面
        this.stopNavigator() // 关闭摄像头
    },
}
</script>
<style>
	.result_img{
         width: 146px;
         height: 195px;
         background: #D8D8D8;
     }
</style>

步骤拆分

html部分

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <title>调用摄像头拍照</title>
</head>
<div id="app">
        <video id="videoCamera" :width="videoWidth" :height="videoHeight" autoplay></video>
        <canvas style="display:none;" id="canvasCamera" :width="videoWidth" :height="videoHeight"></canvas>
        
		<button plain  @click="setImage()">手动拍照</button>
         <p class="fail_tips">这是拍照,请正脸面向摄像头,点击手动拍照</p>
         <!-- 给外面盒子设置宽高,可以限制拍照图片的大小位置范围 -->
         <div class="result_img">
             <img :src="imgSrc" alt class="tx_img" width="100%" />
         </div>
         <p class="res_tips">这是效果展示</p>
    </div>

js部分拆分

1、data数据
vm = new Vue({
            el:'#app',
            data:{
                // 视频调用相关数据开始
                videoWidth: 245,
                videoHeight: 326,
                imgSrc: "",
                thisCancas: null,
                thisContext: null,
                thisVideo: null,
                openVideo:false,
                //视频调用相关数据结束
                postVideoImg:'',// 图片上传后获取的url链接
              
            },
        })
methods方法:第一步开启调用摄像头
vm = new Vue({
		   mounted(){
		   		 // 第一步打开摄像头
                 // 调用摄像头
                 this.getCompetence()
		   },
           methods:{
           		// 调用权限(打开摄像头功能)
                getCompetence() {
                var _this = this;
                _this.thisCancas = document.getElementById("canvasCamera");
                _this.thisContext = this.thisCancas.getContext("2d");
                _this.thisVideo = document.getElementById("videoCamera");
                _this.thisVideo.style.display = 'block';
                // 获取媒体属性,旧版本浏览器可能不支持mediaDevices,我们首先设置一个空对象
                if (navigator.mediaDevices === undefined) {
                    navigator.mediaDevices = {};
                }
                // 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象
                // 使用getUserMedia,因为它会覆盖现有的属性。
                // 这里,如果缺少getUserMedia属性,就添加它。
                if (navigator.mediaDevices.getUserMedia === undefined) {
                    navigator.mediaDevices.getUserMedia = function(constraints) {
                    // 首先获取现存的getUserMedia(如果存在)
                    var 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);
                    });
                    };
                }
                var constraints = {
                    audio: false,
                    video: {
                    width: this.videoWidth,
                    height: 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 => {
                    console.log(err);
                    });
                },
           }   
        })
methods方法:第二步拍照
vm = new Vue({
           methods:{
           		//  第二步、绘制图片(拍照功能)
                setImage() {
                    var _this = this;
                    // canvas画图
                    _this.thisContext.drawImage(
                        _this.thisVideo,
                        0,
                        0,
                    );
                    // 获取图片base64链接
                    var image = this.thisCancas.toDataURL("image/png");
                    _this.imgSrc = image;//赋值并预览图片

                    this.postImg() // 绘制完图片调用图片上传接口
                    
                },
           }   
        })
methods方法:第三步上传拍照
vm = new Vue({
           methods:{
           		// 第三步、拍照图转换file格式上传,
                // 第四步、获取图片url链接
                postImg(){
                    let formData = new FormData()
                    formData.append('file', this.base64ToFile(this.imgSrc,'png'))
                    formData.append("flag", "videoImg")// 额外参数
                    
                    // 对应的后台接口 === app/StudentVideoController/uploadFile
                    this.$axios.post('app/StudentVideoController/uploadFile',formData).then(res => {
                        // console.log(res);
                        if(res.data.code == '00'){
                            // 图片文件传至后台 == 获取到该图片的url路径
                            this.postVideoImg = res.data.FilePath
                            //获得图片的url后,需要做什么
                            //做的事情......
                        }

                    }).catch(error => {
                    console.log(error);
                })

                },
           }   
        })
methods方法:其他—base64图片转换为file , 关闭摄像头
destroyed 离开页面关闭摄像头
vm = new Vue({
           methods:{
           		// 关闭摄像头
                stopNavigator() {
                    this.thisVideo.srcObject.getTracks()[0].stop();
                },

                // base64 转为 file 
                base64ToFile(urlData, fileName) {
                    let arr = urlData.split(',');
                    let mime = arr[0].match(/:(.*?);/)[1];
                    let bytes = atob(arr[1]); // 解码base64
                    let n = bytes.length
                    let ia = new Uint8Array(n);
                    while (n--) {
                        ia[n] = bytes.charCodeAt(n);
                    }
                    	return new File([ia], fileName, { type: mime });
                	},
            	},
           },
           destroyed: function () { // 离开当前页面
        		this.stopNavigator() // 离开页面关闭摄像头
    		},  
        })

css样式

        .result_img{
            width: 146px;
            height: 195px;
            background: #D8D8D8;
        }

调用摄像头拍照效果

在这里插入图片描述

  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值