vue实现PC端调用摄像头拍照人脸录入、移动端调用手机前置摄像头人脸录入、及图片旋转矫正、压缩上传base64格式/文件格式

1. PC端调用摄像头拍照上传base64格式到后台,这个没什么花里胡哨的骚操作,直接看代码 (canvas + video)

<template>
    <div>
        <!--开启摄像头-->
        <img @click="callCamera" :src="headImgSrc" alt="摄像头">
        <!--canvas截取流-->
        <canvas ref="canvas" width="640" height="480"></canvas>
        <!--图片展示-->
        <video ref="video" width="640" height="480" autoplay></video>
        <!--确认-->
        <el-button size="mini" type="primary" @click="photograph"></el-button>
    </div>
</template>   
<script>
export default {
  data () {
    return {
      headImgSrc: require('@/assets/image/photograph.png')
    }
  },
  methods: {
    // 调用摄像头
    callCamera () {
      // H5调用电脑摄像头API
      navigator.mediaDevices.getUserMedia({
        video: true
      }).then(success => {
        // 摄像头开启成功
        this.$refs['video'].srcObject = success
        // 实时拍照效果
        this.$refs['video'].play()
      }).catch(error => {
        console.error('摄像头开启失败,请检查摄像头是否可用!')
      })
    },
    // 拍照
    photograph () {
      let ctx = this.$refs['canvas'].getContext('2d')
      // 把当前视频帧内容渲染到canvas上
      ctx.drawImage(this.$refs['video'], 0, 0, 640, 480)
      // 转base64格式、图片格式转换、图片质量压缩
      let imgBase64 = this.$refs['canvas'].toDataURL('image/jpeg', 0.7)
      
    // 由字节转换为KB 判断大小
      let str = imgBase64.replace('data:image/jpeg;base64,', '')
      let strLength = str.length
      let fileLength = parseInt(strLength - (strLength / 8) * 2)
    // 图片尺寸  用于判断
      let size = (fileLength / 1024).toFixed(2)
      console.log(size)

     // 上传拍照信息  调用接口上传图片 .........

      // 保存到本地
      let ADOM = document.createElement('a')
      ADOM.href = this.headImgSrc
      ADOM.download = new Date().getTime() + '.jpeg'
      ADOM.click()
    },
    // 关闭摄像头
    closeCamera () {
      if (!this.$refs['video'].srcObject) return
      let stream = this.$refs['video'].srcObject
      let tracks = stream.getTracks()
      tracks.forEach(track => {
        track.stop()
      })
      this.$refs['video'].srcObject = null
    },
  }
}
</script>

2. 移动端调用手机前置摄像头人脸录入、及图片旋转矫正、压缩上传base64格式/文件流格式;移动端幺蛾子就多了,比如部分手机打开的不是前置摄像头,部分手机拍照图片旋转了,高清手机拍的图片非常大........

介绍: 1. 通过input 开启手机前置摄像头  accept="image/*" 为开启摄像头  capture="user" 为开启前置摄像头 (微信公众号的话可以微信jssdk,但它不支持前置摄像头,默认后置,所以没用)

    2. 通过 exif.js 判断旋转了多少度在通过canvas矫正

            3. 图片太大或超过规定尺寸则通过canvas压缩

 HTML 部分:

// 压缩图片 and 旋转角度纠正
    compressImage (event) {
      let _this = this
      let file = event.target.files[0]
      let fileReader = new FileReader()
      let img = new Image()
      let imgWidth = ''
      let imgHeight = ''
      // 旋转角度
      let Orientation = null
      // 缩放图片需要的canvas
      let canvas = document.createElement('canvas')
      let ctx = canvas.getContext('2d')// 图片大小  大于2MB 则压缩
      const isLt2MB = file.size < 2097152
      // 通过 EXIF 获取旋转角度 1 为正常  3 为 180°  6 顺时针90°  9 为 逆时针90°
      EXIF.getData(file, function () {
        EXIF.getAllTags(this)
        Orientation = EXIF.getTag(this, 'Orientation')
      })
      // 文件读取 成功执行
      fileReader.onload = function (ev) {
        // 文件base64化,以便获知图片原始尺寸
        img.src = ev.target.result
      }
      // 读取文件
      fileReader.readAsDataURL(file)
      // base64地址图片加载完毕后
      img.onload = function () {
        imgWidth = img.width
        imgHeight = img.height
        canvas.width = img.width
        canvas.height = img.height
        // 目标尺寸
        let targetWidth = imgWidth
        let targetHeight = imgHeight
        // 不需要压缩 不需要做旋转处理
        if (isLt2MB && imgWidth < 960 && imgHeight < 960 && !Orientation) return _this.XMLHttpRequest(file)
        if (isLt2MB && imgWidth < 960 && imgHeight < 960 && +Orientation === 1) return _this.XMLHttpRequest(file)
        // 大于2MB 、img宽高 > 960 则进行压缩
        if (!isLt2MB || imgWidth >= 960 || imgHeight >= 960) {
          // 最大尺寸
          let maxWidth = 850
          let maxHeight = 850
          // 图片尺寸超过 960 X 960 的限制
          if (imgWidth > maxWidth || imgHeight > maxHeight) {
            if (imgWidth / imgHeight > maxWidth / maxHeight) {
              // 更宽,按照宽度限定尺寸
              targetWidth = maxWidth
              targetHeight = Math.round(maxWidth * (imgHeight / imgWidth))
            } else {
              targetHeight = maxHeight
              targetWidth = Math.round(maxHeight * (imgWidth / imgHeight))
            }
          }
          // canvas对图片进行缩放
          canvas.width = targetWidth
          canvas.height = targetHeight
          // 图片大小超过 2Mb 但未旋转  则只需要进行图片压缩
          if (!Orientation || +Orientation === 1) {
            ctx.drawImage(img, 0, 0, targetWidth, targetHeight)
          }
        }
        // 拍照旋转 需矫正图片
        if (Orientation && +Orientation !== 1) {
          switch (+Orientation) {
            case 6:     // 旋转90度
              canvas.width = targetHeight
              canvas.height = targetWidth
              ctx.rotate(Math.PI / 2)
              // 图片渲染
              ctx.drawImage(img, 0, -targetHeight, targetWidth, targetHeight)
              break
            case 3:     // 旋转180度
              ctx.rotate(Math.PI)
              // 图片渲染
              ctx.drawImage(img, -targetWidth, -targetHeight, targetWidth, targetHeight)
              break
            case 8:     // 旋转-90度
              canvas.width = targetHeight
              canvas.height = targetWidth
              ctx.rotate(3 * Math.PI / 2)
              // 图片渲染
              ctx.drawImage(img, -targetWidth, 0, targetWidth, targetHeight)
              break
          }
        }
        // base64 格式   我这是vuex 形式 重点是 canvas.toDataURL('image/jpeg', 1)
        // _this.$store.commit('SAVE_FACE_IMAGE_BASE64', canvas.toDataURL('image/jpeg', 1))
     // 调用接口上传
        // _this.upAppUserFaceByBase64()
        // 通过文件流格式上传
     canvas.toBlob(function (blob) {
          _this.XMLHttpRequest(blob)
        }, 'image/jpeg', 1)
      }
    },
    // 上传base64方式
    upAppUserFaceByBase64 () {
      this.$store.dispatch('upAppUserFaceByBase64', {
        baseFace: this.$store.state.faceImageBase64
      }).then(res => {
        // 上传成功
      }).catch(err => {
        console.log(err)
      })
    },
    // 上传
    XMLHttpRequest (params) {
      // 图片ajax上传
    let action = '后台接口地址'
      let xhr = new XMLHttpRequest()
    let formData = new FormData()
      formData.delete('multipartFile')
      formData.append('multipartFile', params)
      // 文件上传成功
      xhr.onprogress = this.updateProgress
      xhr.onerror = this.updateError
      // 开始上传
      xhr.open('POST', action, true)
      xhr.send(formData)
    },
    // 上传成功回调
    updateProgress (res) {
      // res 就是成功后的返回 
    },
    // 上传失败回调
    updateError (error) {
      console.log(error)
    },
### 回答1: UniApp是一种基于Vue.js框架开发的多端应用开发框架,可以轻松地开发出运行在微信小程序、App、H5、快应用等平台上的应用程序。为了在UniApp中通过前置摄像头拍摄照片或者录制视频,我们需要调用uni.chooseVideo和uni.chooseImage这两个API。 其中,uni.chooseVideo实现调用前置摄像头的功能,可以通过以下步骤来实现: 1. 在uni-app项目的pages.json文件中注册一个页面,比如:video. 2. 在video.vue文件中通过调用uni.chooseVideo()方法来控制前置摄像头的开启。 3. 在uni.chooseVideo()的配置参数中,设置camera属性为“front”,即可调用前置摄像头。 具体实现代码如下所示: <template> <view> <button @tap="takeVideo">调用前置摄像头</button> </view> </template> <script> export default { methods: { takeVideo(){ uni.chooseVideo({ camera: 'front', // 调用前置摄像头 maxDuration: 60, success: function (res) { console.log(res.tempFilePaths[0]) } }) } } } </script> 通过上述方法,我们可以在uni-app中调用前置摄像头来拍摄或录制视频,并且可以根据自己的需求自定义参数来实现更多的自定义功能。 ### 回答2: Uniapp是一款跨平台开发框架,它通过一套代码可以在多个平台上运行,包括Android、iOS、H5等。如果我们想要在Uniapp中调用前置摄像头,需要进行以下步骤。 首先,在我们的项目中安装uni-chose-image插件,它可以提供一个包含相机、相册、预览等功能的页面,相机模块默认使用的是后置摄像头,因此我们需要设定使用前置摄像头。 其次,在页面的mounted函数中,找到uni.chooseImage的函数调用。根据文档,我们可以看到它接受一个对象作为参数,该对象包含count、scope、sizeType、sourceType和success等属性。其中,scope属性可以用来设定使用的摄像头,其取值有camera表示后置摄像头,frontCamera表示前置摄像头,unspecified表示不指定使用哪个摄像头。 最后,我们需要在manifest.json文件中,声明我们的应用需要使用摄像头权限。可以在app-plus节点中的nvue节点中添加支持的权限名称,例如camera。这样,当我们在使用uni.chooseImage函数时,系统会弹出一个权限请求对话框,询问用户是否授权应用使用摄像头。 综上所述,如果我们想在Uniapp中调用前置摄像头,我们需要安装uni-chose-image插件,在mounted函数中配置使用前置摄像头,以及在manifest.json文件中声明应用需要使用摄像头权限。通过这些步骤,我们可以很方便地实现前置摄像头调用。 ### 回答3: Uniapp是一种跨平台的开发框架,开发者可以在不同的平台上快速地实现应用的开发。在Uniapp的应用中,调用前置摄像头可以帮助开发者实现许多在应用中需要使用的功能。以下是Uniapp调用前置摄像头的详细说明: 首先,在Uniapp中调用前置摄像头需要使用到uni-app插件,这个插件可以帮助开发者快速地实现在不同平台中使用前置摄像头的功能。 其次,在使用前置摄像头的时候,开发者需要注意以下两个问题: 1. 平台差异性:因为不同的平台上支持前置摄像头的方式不同,所以开发者需要在不同的平台上分别实现调用前置摄像头的方法。在uni-app插件中,可以使用#ifdef、#endif来判断需要调用的平台是哪个,然后进行相应的调用。 2. 权限问题:在调用前置摄像头时,开发者需要注意权限问题,不同的平台上可能需要不同的权限才能使用前置摄像头。在uni-app插件中,可以使用uni.requestAuth来请求相应的权限。在获取到权限之后,就可以正常地调用前置摄像头了。 最后,在进行前置摄像头调用时,需要注意一些技巧。例如,在使用前置摄像头进行拍照时,需要指定前置摄像头的ID。在uni-app插件中,可以使用uni.getSystemInfoSync获取到摄像头的ID,然后通过camera组件来进行拍照。此外,还需要注意前置摄像头和后置摄像头的差异,例如拍照时需要注意照片的方向等问题。 总之,在使用Uniapp调用前置摄像头的过程中,需要注意平台差异性、权限问题、技巧等方面,才能够顺利实现调用前置摄像头的功能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值