h5拍照旋转,压缩,裁剪及使用方法

修正图片角度需要EXIF.js,这里是npm安装后使用

import { EXIF } from 'exif-js';
/**
 * 压缩图片
 * @param {file} 输入图片
 * @returns {Promise} resolved promise 返回压缩后的新图片
 */
function compressImage(file) {
  return new Promise((resolve, reject) => {
    // 获取图片(加载图片是为了获取图片的宽高)
    const img = new Image();
    img.src = window.URL.createObjectURL(file);
    img.onerror = error => reject(error);
    img.onload = () => {
      // 画布宽高
      const canvasWidth = document.documentElement.clientWidth * window.devicePixelRatio;
      const canvasHeight = document.documentElement.clientHeight * window.devicePixelRatio;

      // 计算缩放因子
      // 这里我取水平和垂直方向缩放因子较大的作为缩放因子,这样可以保证图片内容全部可见
      const scaleX = canvasWidth / img.width;
      const scaleY = canvasHeight / img.height;
      const scale = Math.min(scaleX, scaleY);

      // 将原始图片按缩放因子缩放后,绘制到画布上
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext("2d");
      canvas.width = canvasWidth;
      canvas.height = canvasHeight;
      const imageWidth = img.width * scale;
      const imageHeight = img.height * scale;
      const dx = (canvasWidth - imageWidth) / 2;
      const dy = (canvasHeight - imageHeight) / 2;
      ctx.drawImage(img, dx, dy, imageWidth, imageHeight);
      // 导出新图片
      // 指定图片 MIME 类型为 'image/jpeg', 通过 quality 控制导出的图片质量,进行实现图片的压缩
      const quality = 0.92
      canvas.toBlob(file => resolve(tempFile), "image/jpeg", quality);
    };
  });
},
/**
 * 修正图片旋转角度问题
 * @param {file} 原图片
 * @return {Promise} resolved promise 返回纠正后的新图片
 */
function fixImageOrientation (file) {
  return new Promise((resolve, reject) => {
    // 获取图片
    const img = new Image();
    img.src = window.URL.createObjectURL(file);
    img.onerror = () => resolve(file);
    img.onload = () => {
      // 获取图片元数据(EXIF 变量是引入的 exif-js 库暴露的全局变量)
      EXIF.getData(img, function() {
        // 获取图片旋转标志位
        var orientation = EXIF.getTag(this, "Orientation");
        // 根据旋转角度,在画布上对图片进行旋转
        if (orientation === 3 || orientation === 6 || orientation === 8) {
          const canvas = document.createElement("canvas");
          const ctx = canvas.getContext("2d");
          switch (orientation) {
            case 3: // 旋转180°
              canvas.width = img.width;
              canvas.height = img.height;
              ctx.rotate((180 * Math.PI) / 180);
              ctx.drawImage(img, -img.width, -img.height, img.width, img.height);
              break;
            case 6: // 旋转90°
              canvas.width = img.height;
              canvas.height = img.width;
              ctx.rotate((90 * Math.PI) / 180);
              ctx.drawImage(img, 0, -img.height, img.width, img.height);
              break;
            case 8: // 旋转-90°
              canvas.width = img.height;
              canvas.height = img.width;
              ctx.rotate((-90 * Math.PI) / 180);
              ctx.drawImage(img, -img.width, 0, img.width, img.height);
              break;
          }
          // 返回新图片
          canvas.toBlob(file => resolve(file), 'image/jpeg', 0.92)
        } else {
          return resolve(file);
        }
      });
    };
  });
}
/**
 * 裁剪图片
 * @param {file} 输入图片
 * @returns {Promise} resolved promise 返回压缩后的新图片
 */
function cutImage(file) {
  return new Promise((resolve, reject) => {
    // 获取图片(加载图片是为了获取图片的宽高)
    const img = new Image();

    img.src = window.URL.createObjectURL(file);
    img.onerror = error => reject(error);
    img.onload = () => {
      const imgWidth = img.width;
      const imgHeight = img.height;
      const scale = imgWidth / imgHeight;
      // 这里直接把宽度除以2然后等比算出高度,如果不想每次砍一半可以自己修改
      // const width1 = imgWidth - 500;   每次减500
      const width1 = imgWidth / 2;
      const height1 = parseInt(width1 / scale, 10);

      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');

      canvas.width = width1;
      canvas.height = height1;
      ctx.drawImage(img, 0, 0, imgWidth, imgHeight, 0, 0, width1, height1);
      canvas.toBlob(_file => resolve(_file), 'image/jpeg');
    };
  });
}
/**
 * 本地图片预览地址
 * @param {file} 原图片
 * @return blob地址
 */
function getObjectURL(file) {
  let url = null;

  if (window.createObjcectURL !== undefined) {
    url = window.createOjcectURL(file);
  } else if (window.URL !== undefined) {
    url = window.URL.createObjectURL(file);
  } else if (window.webkitURL !== undefined) {
    url = window.webkitURL.createObjectURL(file);
  }
  return url;
}

使用方法:

// 拍照
  takePhoto = (e) => {
    // 不管用什么方法获得的图片文件
    const file = e.target.files[0];

    if (file) {
      // 先把图片旋转至正向
      fixImageOrientation(file).then(fixFile => {
        this.takePhotoNext(fixFile);
      });
    }
  }

takePhotoNext = (file) => {
    if (file.size > 1024 * 1024 * 4) {
      // 如果图片大于4M则压缩,然后重新调用方法看是不是还大于4M,
      // 大于的话继续压缩,不大于4M则裁切
      compressImage(file).then(_file => {
        this.takePhotoNext(_file);
      });
    } else {
      this.cutPhoto(file);
    }
  }

cutPhoto = (file) => {
    const img = new Image();

    img.src = window.URL.createObjectURL(file);
    img.onload = () => {
      // 如果宽大于1920或高大于1080,重复调用至满足要求
      if (img.width > 1920 || img.height > 1080) {
        // 裁切图片
        cutImage(file).then(_file => {
          this.cutPhoto(_file);
        });
      } else {
        // 最后的文件,想干嘛干嘛,我这里生成img的src打印出来
        console.log(getObjectURL(file));
      }
    };
  }

你可能感兴趣的:(h5拍照旋转,压缩,裁剪及使用方法)