Vue实现网页在线拍照和上传

项目背景:

用 vue-cli + element-ui 开发的项目

 

方法一(不支持360兼容模式、IE):使用 mediaDevices.getUserMedia()

代码如下:

<template>
  <div class="take-photo">
    <!-- 拍照 -->
    <video id="videoCamera" :width="videoWidth" :height="videoHeight" autoPlay></video>
    <el-button size="small" type="primary" @click="takePhotoHandle">拍照</el-button>
    <!-- 预览 -->
    <canvas id="canvasCamera" :width="videoWidth" :height="videoHeight"></canvas>
    <el-button size="small" type="primary" :loading="loading" @click="uploadHandle">上传</el-button>
  </div>
</template>

<script>
export default {
  name: 'takePhoto',
  data () {
    return {
      loading: false, // 上传照片的loading
      imgSrc: "", // 照片地址
      photoVideo: null, // 拍照框
      photoContext: null, // canvas绘图环境
      photoCancas: null, // 预览框
      videoWidth: 306, // 拍照框宽度
      videoHeight: 378, // 拍照框高度
    }
  },
  mounted () {
    // 打开摄像头
    this.openCamera()
  },
  beforeDestroy() {
    if (this.photoVideo && this.photoVideo.srcObject) {
      // 停止视频流
      this.photoVideo.srcObject.getTracks()[0].stop();
    }
  },
  methods: {
    // 拍照处理
    takePhotoHandle () {
      // canvas画图
      this.photoContext.drawImage(this.photoVideo, 0, 0, this.videoWidth, this.videoHeight)
      // 获取图片base64链接
      this.imgSrc = this.photoCancas.toDataURL('image/png')
    },
    // 打开摄像头
    async openCamera() {
      this.photoVideo = document.getElementById('videoCamera')
      this.photoCancas = document.getElementById('canvasCamera')
      this.photoContext = this.photoCancas.getContext('2d')
      try {
        const constraints = {
          audio: false,
          video: {
            width: this.videoWidth,
            height: this.videoHeight
          }
        }
        const stream = await navigator.mediaDevices.getUserMedia(constraints)
        this.photoVideo.srcObject = stream
        this.photoVideo.play()
      } catch (error) {
        this.$message({
          title: '警告',
          message: '请确认摄像头能正常工作,必须使用谷歌浏览器或者360浏览器的极速模式,否则拍照不能正常使用',
          type: 'warning',
          duration: 8000
        });
      }
    },
    // 上传照片
    async uploadHandle () {
      this.loading = true
      try {
        const firstIndex = this.imgSrc.indexOf('base64,')
        const url = this.imgSrc.substr(firstIndex + 7)
        const params = {
          photo: url
        }
        // 发送接口
        await xxx(params)
        this.loading = false
      } catch (error) {
        this.loading = false
      }
    }
  }
}
</script>

<style lang="scss" scoped>
</style>

 

方法二(兼容360兼容模式、IE):使用 webcamjs

实现步骤:

1、安装适合浏览器的flash:https://www.flash.cn/download-wins

为了兼容IE,我下载的是下图版本:

2、将 webcam.min.js 和 webcam.swf 文件,放到根目录——>public目录中。

这两个文件可以在 webcamjs的github上拿到:https://github.com/jhuckaby/webcamjs

3、public目录下的index.html,在头部引入  webcam.min.js。

4、takePhoto.vue是拍照页,其中代码如下:

 <template>
   <div class="take-photo">
     <!-- 拍照 -->
     <div id="photoCamera"></div>
     <el-button size="small" type="primary" @click="takePhotoHandle">拍照</el-button>
     <!-- 预览 -->
     <div id="imageCamera"></div>
     <el-button size="small" type="primary" :loading="loading" @click="uploadHandle">上传</el-button>
   </div>
 </template>
 
 <script>
 export default {
   name: 'takePhoto',
   data () {
     return {
       loading: false, // 上传照片的loading
       imgSrc: "",
       videoWidth: 306,
       videoHeight: 378,
     }
   },
   mounted () {
     Webcam.set({
       width: this.videoWidth,
       height: this.videoHeight,
       image_format: 'jpeg',
       jpeg_quality: 100,
       swfURL: '../../webcam.swf', // 指定swf文件
     })
     Webcam.attach('#photoCamera')
   },
   methods: {
     // 拍照处理
     takePhotoHandle () {
       Webcam.snap(url => {
         this.imgSrc = url
         document.getElementById('imageCamera').innerHTML = `<img src="${url}">`
       })
     },
     // 上传照片
     async uploadHandle () {
       this.loading = true
       try {
         const firstIndex = this.imgSrc.indexOf('base64,')
         const url = this.imgSrc.substr(firstIndex + 7)
         const params = {
           photo: url
         }
         // 调接口
         await xxx(params)
         this.loading = false
       } catch (error) {
         this.loading = false
       }
     },
   }
 }
 </script>
 
 <style lang="scss" scoped>
 </style>

 

使用方法二时,注意 && 补充:

1、安装完 flash 后,当浏览器访问拍照页面时,会弹出下图提示,选择 一键打开。

 

 

 2、前端框架开发的项目,Webcam.set 中的 swfURL 配置很重要。

swfURL:配置webcam.swf的文件路径。

测试是否设置成功:在浏览器中,要能访问到这个文件。

比如我把swf文件放在根目录——>public目录下,拍照的访问地址是 http://localhost/student/photo/takePhoto

那么swfURL设置为 "../../webcam.swf"。 当访问 http://localhost/webcam.swf,是可以访问到这个swf文件的。

这个swf很重要,访问不到的话,就会出现:明明有了flash,但拍照框里一片空白。因为这个swf就是询问你是否愿意打开摄像头的,允许了才可以打开摄像头。

这个swf就是下面这个文件:

 

3、如何不用询问,直接打开摄像头呢?

拍照画面,鼠标右键——>设置,打开下图,勾选“允许”和“记住”。

想了解详细的话,可以点击弹窗右上角的 “?” 查看。

 

4、参考资料:

webcamjs的github地址:https://github.com/jhuckaby/webcamjs

webcamjs支持h5以及flash的方式调用摄像头:https://www.zybuluo.com/Fancy-Bai/note/725731

webcamjs的中文简介:https://crazyhuiliang.gitbooks.io/javascript/content/WebcamJS.html

 

 

 

背后心得:

现在解决了,便会觉得也没啥大不了。但遇到问题的当时,真的是很头疼。 

每次听到要在IE上用,头都大了,白眼翻到九霄云外。

一开始以为是flash的问题,装了卸,卸了装,搞了一天。后来遇到空白的问题,都要放弃了,
后端小伙伴说放弃吧,换个方法吧,研究下ActiveX拍照控件。

What ? NONONO,花了这么久捯饬,不给个结果,对不起掉的头发。总感觉真相就隔着一层纸。

结果真的找到了swf这个原因,摄像头打开的时候,眼泪都要出来了。

测试容易走神:总是看到低画质无美颜的大脸,心情都糟了。

上一篇博客是两年多前,现在逼着自己把这个整理了,短短的文章,竟然也从1点多写到4点多 ==||

 

posted @ 2021-12-01 16:45  幸福n-1次方  阅读(1634)  评论(0编辑  收藏  举报