H5拍照上传处理

前言


很多公司业务中,会存在上传资料图片,以供审核的需求。那我们用H5如何实现,并达到好的效果呢

涉及技术点:

  • html media capture
  • FileReader || ULR.createObjectURL()
  • canvas
  • EXIF & orientation

调用相机

html media capture

<input type='file' accept='image/*' capture="camera"/>

获取图片信息


以下两种方式皆可:

  • new FileReader().readAsDataURL(file) 异步/data:base64
  • ULR.createObjectURL(file) 同步/内存url

压缩


  • 限制最大宽度,对宽高做处理
  • 等比例压缩
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  canvas.width = Math.min(image.naturalWidth, option.maxWidth)
  // 高度通过宽度压缩比处理,保证等比例压缩
  const ratio = canvas.width / image.naturalWidth
  canvas.height = image.naturalHeight * ratio
  ...
  // 二次压缩(比如90%)
  canvas.toDataURL(fileType, 0.9); // fileType: image/jpeg

旋转处理


手机相机(基本上都是Iphone)拍照,你会发现有时候照片会自动旋转,有时候并不是我们期望的显示效果。
不过手机拍照获取的图片,有EXIF(Exchangeable image file format),会默认设置一个orientation tag(jpeg格式才有)。orientation标示了图片旋转信息。

首先,我们可以用Exifjs获取orientation。Exif.js提供了js读取图像的原始数据的功能扩展(拍照方向、相机设备型号、拍摄时间、ISO感光度、GPS地理位置等数据).

import EXIF from 'exif-js';
...

EXIF.getData(file, function () {
  const orientation = EXIF.getTag(this, 'Orientation');
  console.log(`orientation: ${orientation}`);
});

然后,我们用canvas对图片做一些旋转处理即可( 亲测只存在1,3,6,8四种情况):

  // 判断图片方向,重置 canvas 大小,确定旋转角度,iphone 默认的是 home 键在右方的横屏拍摄方式
  switch (orientation) {
      // 1 不需要旋转
      case 1: {
          ctx.drawImage(img, 0, 0, width, height);
          ctx.clearRect(0, 0, width, height);
          ctx.drawImage(img, 0, 0, width, height);
          break;
      }
      // iphone 横屏拍摄,此时 home 键在左侧 旋转180度
      case 3: {
          ctx.clearRect(0, 0, width, height);
          ctx.translate(0, 0);
          ctx.rotate(Math.PI);
          ctx.drawImage(img, -width, -height, width, height);
          break;
      }
      // iphone 竖屏拍摄,此时 home 键在下方(正常拿手机的方向) 旋转90度
      case 6: {
          ctx.clearRect(0, 0, width, height);
          ctx.translate(0, 0);
          ctx.rotate(90 * Math.PI / 180);
          ctx.drawImage(img, 0, -height, width, height);
          break;
      }
      // iphone 竖屏拍摄,此时 home 键在上方 旋转270度
      case 8: {
          ctx.clearRect(0, 0, width, height);
          ctx.translate(0, 0);
          ctx.rotate(-90 * Math.PI / 180);
          ctx.drawImage(img, -width, 0, width, height);
          break;
      }
      default: {
          ctx.clearRect(0, 0, width, height);
          ctx.drawImage(img, 0, 0, width, height);
          break;
      }
  }

最后,我们上传处理完的图片。


参考资料