current position:Home>JavaScript implements calling the camera to complete taking pictures, renaming and downloading or uploading

JavaScript implements calling the camera to complete taking pictures, renaming and downloading or uploading

2022-08-05 16:47:32AI Thabo

环境条件

  • Has a built-in camera 或 Peripheral camera
  • Vue + Element + axios(Different environments can be modified by yourself,This article is mostly logic,In addition to the upload control displayed, other andjs基本无异)

全文

<template>
  <div id="all">
    <el-upload
      :headers="{token:userinfo.token}"
      class="upload-demo"
      list-type="picture-card"
      :multiple="false"
      :limit="5"
      :action="uploadimgUrl"
      :on-success="uploadPhoto"
      :on-remove="handleRemovePhoto"
      :file-list="fileListimg"
      multiple>
      <i class="el-icon-plus"></i>
    </el-upload>

    <div class="gp">
      <video ref="gpp2"></video>
    </div>
    <div class="footer" style="display: flex;justify-content: space-between;margin-top: 10px">
      <el-button type="primary" @click="takeGpp">抓 拍 上 传</el-button>
    </div>
    <canvas ref="canvas" v-show="false" height="960" width="1600"></canvas>

  </div>
</template>

<script>
import request from "@/utils/request";

export default {
  name: "demo",
  data(){
    let url = process.env.VUE_APP_BASE_API;
    let baseUrl = this.$baseUrl;
    let userinfo = JSON.parse(sessionStorage.getItem('userinfo'))
    return{
      fileListimg:[],
      fileliststr:"",
      video:{},
      baseUrl,
      userinfo,
      uploadimgUrl:url+"/upload_images",

    }
  },
  mounted() {
    this.initGpp();
  },
  methods:{
    openGpp() {
      // this.dialogFormVisible = true;
      setTimeout(() => {
        this.initGpp();
      }, 100)
    },
    initGpp() {
      this.video = this.$refs.gpp2;
      console.log(this.video)
      // this.video = document.getElementById('video')
      //兼容性写法,判断getUserMedia方法是否存在
      navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || window.getUserMedia;
      if (navigator.getUserMedia) {
        //调用用户媒体设备, 访问摄像头
        this.getUserMedia({video: {width: 1600, height: 960}}, this.success, this.error);
      } else {
        alert('不支持访问用户媒体');
      }
    },
    getUserMedia(constraints, success, error) {
      if (navigator.mediaDevices.getUserMedia) {
        //最新的标准API
        navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);
      } else if (navigator.webkitGetUserMedia) {
        //webkit核心浏览器
        navigator.webkitGetUserMedia(constraints, success, error)
      } else if (navigator.mozGetUserMedia) {
        //firfox浏览器
        navigator.mozGetUserMedia(constraints, success, error);
      } else if (navigator.getUserMedia) {
        //旧版API
        navigator.getUserMedia(constraints, success, error);
      }
    },
    // 调用成功的方法
    success(stream) {
      //兼容webkit核心浏览器
      let CompatibleURL = window.URL || window.webkitURL;
      //将视频流设置为video元素的源
      // console.log(stream);

      //video.src = CompatibleURL.createObjectURL(stream);
      //Assign the video captured by the camera to viedeo的srcObject属性
      //src是视频文件,srcObjectis a live stream
      //The webcam is a live stream
      this.video.srcObject = stream;
      //并播放
      this.video.play();
    },
    // The method that failed to call
    error(error) {
      console.log(`访问用户媒体设备失败${error.name}, ${error.message}`);
    },
    takeGpp() {
      if(this.fileListimg.length>=5){
        this.$message({
          type: 'error',
          message: "A maximum of five images are allowed"
        });
        return
      }

      let canvas = this.$refs.canvas;
      var context = canvas.getContext("2d");
      //Convert the current page of the video to a picture,displayed on the artboard
      context.drawImage(this.video, 0, 0,);
      //把canvas图像转为img图片
      var src = canvas.toDataURL("image/jpeg");
      // console.log(src)
      let file = this.base64ToFile(src);
      let time = new Date().getTime();

      // this.downloadFile(file, `${time}.png`)
      let type = file.type.split('/');
      let renameFile = new File([file],time+".png",{type:"image/png"})

      let formData = new FormData();
      formData.append('file',renameFile)

      request({
        url:"/upload_images",
        method:"post",
        data:formData
      }).then(res => {
        console.log(res)
        this.$message({
          type: 'success',
          message: "上传成功"
        });
        this.fileListimg.push({
          status:"success",
          name:time+".png",
          uid:time,
          url:this.baseUrl + res.data.imgurl,
          response:res
        })
      })
    },
    base64ToFile(base64Data, fileName) {
      let arr = base64Data.split(','),
        fileType = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        l = bstr.length,
        u8Arr = new Uint8Array(l);

      while (l--) {
        u8Arr[l] = bstr.charCodeAt(l);
      }
      return new File([u8Arr], fileName, {type: fileType});
    },
    downloadFile(content, filename) {
      var a = document.createElement('a')
      var blob = new Blob([content])
      var url = window.URL.createObjectURL(blob)
      a.href = url
      a.download = filename
      a.click()
      console.log(url)
      window.URL.revokeObjectURL(url)
    },
    handleRemovePhoto(file, fileList) {
      console.log(file, fileList);
      this.fileListimg = fileList;
      // let index=null;
      // fileList.map((item,i)=> {
      //   if(file.uid === item.uid){
      //     index = i;
      //   }
      // })
      // fileList.splice(index,1);
    },
    uploadPhoto(response, file, fileList) {
      file.url = this.baseUrl+response.data.imgurl;
      console.log(fileList)
      this.fileliststr = JSON.stringify(fileList)
      if(response.code == 0){
        // this.info.fujian = response.data.imgurl;
        // this.info.fujian_name = response.file_name;
      }else{
        // this.fileList = [];
        this.$message({
          type: 'error',
          message: response.msg
        });
      }
    },
  }
}
</script>

<style lang="scss" scoped>
#all {
  min-height: 100vh;
  background-color: #F5F7FD;
  padding: 10px 30px 60px;
  .gp {
    margin-top: 40px;
    height: 480px;
    width: 800px;

    video {
      height: 100%;
      width: 100%;
    }
  }

}
</style>

  1. 静态效果
    演示效果
  2. After the photo is taken(The components shown above are Element的upload的list-type="picture-card"模式)

在这里插入图片描述

步骤解析

  1. 需要一个video控件和一个canvas控件(可隐藏)
  • canvasThe size will determine the final image size and quality
<div class="gp">
      <video ref="gpp2"></video>
</div>
<div class="footer" style="display: flex;justify-content: space-between;margin-top: 10px">
	<el-button type="primary" @click="takeGpp">抓 拍 上 传</el-button>
</div>
<canvas ref="canvas" v-show="false" height="960" width="1600"></canvas>
    
  • Here I use one fromElement的upload组件来展示,Although you probably don't need to
	<el-upload
      :headers="{token:userinfo.token}"
      class="upload-demo"
      list-type="picture-card"
      :multiple="false"
      :limit="5"
      :action="uploadimgUrl"
      :on-success="uploadPhoto"
      :on-remove="handleRemovePhoto"
      :file-list="fileListimg"
      multiple>
      <i class="el-icon-plus"></i>
    </el-upload>

	handleRemovePhoto(file, fileList) {
      console.log(file, fileList);
      this.fileListimg = fileList;
    },
    uploadPhoto(response, file, fileList) {
      if(response.code == 0){
     	 file.url = this.baseUrl+response.data.imgurl;
     	 this.fileliststr = JSON.stringify(fileList)
      }else{
        this.$message({
          type: 'error',
          message: response.msg
        });
      }
    },
  1. 准备数据
  • 除了fileListimgvideo其他都不是必须的,Prepare according to your own needs
data(){
    let url = process.env.VUE_APP_BASE_API;
    let baseUrl = this.$baseUrl;
    let userinfo = JSON.parse(sessionStorage.getItem('userinfo'))
    return{
      fileListimg:[],
      fileliststr:"",
      video:{},
      baseUrl,
      userinfo,
      uploadimgUrl:url+"/upload_images",
    }
  },
  1. 初始化video和摄像头
  • There are many tutorials online for this step
  • Called after the page is renderedinitGpp()
initGpp() {
      this.video = this.$refs.gpp2;
      console.log(this.video)
      // this.video = document.getElementById('video')
      //兼容性写法,判断getUserMedia方法是否存在
      navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || window.getUserMedia;
      if (navigator.getUserMedia) {
        //调用用户媒体设备, 访问摄像头
        this.getUserMedia({video: {width: 1600, height: 960}}, this.success, this.error);
      } else {
        alert('不支持访问用户媒体');
      }
    },
    getUserMedia(constraints, success, error) {
      if (navigator.mediaDevices.getUserMedia) {
        //最新的标准API
        navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);
      } else if (navigator.webkitGetUserMedia) {
        //webkit核心浏览器
        navigator.webkitGetUserMedia(constraints, success, error)
      } else if (navigator.mozGetUserMedia) {
        //firfox浏览器
        navigator.mozGetUserMedia(constraints, success, error);
      } else if (navigator.getUserMedia) {
        //旧版API
        navigator.getUserMedia(constraints, success, error);
      }
    },
    // 调用成功的方法
    success(stream) {
      //兼容webkit核心浏览器
      let CompatibleURL = window.URL || window.webkitURL;
      //将视频流设置为video元素的源
      // console.log(stream);

      //video.src = CompatibleURL.createObjectURL(stream);
      //Assign the video captured by the camera to viedeo的srcObject属性
      //src是视频文件,srcObjectis a live stream
      //The webcam is a live stream
      this.video.srcObject = stream;
      //并播放
      this.video.play();
    },
    // The method that failed to call
    error(error) {
      console.log(`访问用户媒体设备失败${error.name}, ${error.message}`);
    }
  1. 拍照
  • 这一步是重点
  • 上传下载Decide at this step
  • 具体看注释
	takeGpp() {
	  // Some preliminary verification can be done here 
      if(this.fileListimg.length>=5){
        this.$message({
          type: 'error',
          message: "A maximum of five images are allowed"
        });
        return
      }

      let canvas = this.$refs.canvas;
      var context = canvas.getContext("2d");
      //Convert the current page of the video to a picture,displayed on the artboard
      context.drawImage(this.video, 0, 0,);
      //把canvas图像转为img图片
      var src = canvas.toDataURL("image/jpeg");
      let file = this.base64ToFile(src);
      // 获取时间,Prepare as a filename
      let time = new Date().getTime();
	  
	  // Download if you need it,Then please uncomment the next line,And delete everything below the next line
      // this.downloadFile(file, `${time}.png`)
      
      // Rename the file and change the format 
      let type = file.type.split('/');
      let renameFile = new File([file],time+".png",{type:"image/png"})

      let formData = new FormData();
      formData.append('file',renameFile)
	// 上传 request封装方法 继续阅读
      request({
        url:"/upload_images",
        method:"post",
        data:formData
      }).then(res => {
        console.log(res)
        this.$message({
          type: 'success',
          message: "上传成功"
        });
        // 这里是为了使用Element的uploadComponent display is done,Add similarly structured data to the array
        // Please according to your own needs
        this.fileListimg.push({
          status:"success",
          name:time+".png",
          uid:time,
          url:this.baseUrl + res.data.imgurl,
          response:res
        })
      })
    },
    base64ToFile(base64Data, fileName) {
      let arr = base64Data.split(','),
        fileType = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        l = bstr.length,
        u8Arr = new Uint8Array(l);

      while (l--) {
        u8Arr[l] = bstr.charCodeAt(l);
      }
      return new File([u8Arr], fileName, {type: fileType});
    },
    // Download will use this method
    downloadFile(content, filename) {
      var a = document.createElement('a')
      var blob = new Blob([content])
      var url = window.URL.createObjectURL(blob)
      a.href = url
      a.download = filename
      a.click()
      console.log(url)
      window.URL.revokeObjectURL(url)
    }
  1. 大功告成

request.js

  • 参考了Vue-admin-template的封装设计
import axios from 'axios'
import { MessageBox, Message } from 'element-ui'
import store from '@/store'


const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  timeout: 10000 // request timeout
})


service.interceptors.request.use(
  config => {

    let token = sessionStorage.getItem("token")
    if(token){
      config.headers['token'] = token;
    }

    return config
  },
  error => {
    console.log(error) 
    return Promise.reject(error)
  }
)

service.interceptors.response.use(

  response => {
    const res = response.data
    if (res.code === 3) {
      // 未登录
      Message.error("未登录")

      store.dispatch('user/logout').then(() => {
        location.reload()
      })
      return Promise.reject(new Error(res.message || 'Error'))
    }
    return res


  },
  error => {
    console.log('err' + error) // for debug
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)

export default service

copyright notice
author[AI Thabo],Please bring the original link to reprint, thank you.
https://en.hqmana.com/2022/217/202208051642194634.html

Random recommended