前端压缩图片方案

导读:

前端压缩图片,是个常见的需求,特别是要求移动端上传图片(证件上传等),因移动网络不肯定因素,上传特别慢,须要在前端进行图片压缩再上传给服务器来保证用户体验,现就canvas为主技术来实现,下面介绍一下图片压缩:前端

图片压缩方案步骤:

  • 一、使用 window的api FileReader,对File对象进行读取
  • 二、读取到文件后,运用H5 canvas属性,canvas.toDataURL 转化成base64格式的文件,并进行压缩,原理是qualit或像素(宽高)进行减少
  • 三、运用 Uint8Array 对象,对base64进行转换,转换成Files或Blob对象
  • 四、若是有须要,封装成FormData对象

注意事项: IOS在调用canvas.toDataURL存在限制,最明显的是长宽像素,不能超过4500,不然会出现浏览器崩溃现象node

import { isIos } from '../../utils/utils';
/**
 * photoCompress input前端传入File对象,读取成URL
 * @param file File对象
 * @param w 压缩等参数
 * @param objDiv 生成压缩的回调
 */
function photoCompress(file, w, objDiv) {
  const ready = new window.FileReader();
  /* 开始读取指定的Blob对象或File对象中的内容. 当读取操做完成时,
    readyState属性的值会成为DONE,若是设置了onloadend事件处理程序,
    则调用之.同时,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容.
  */
  ready.readAsDataURL(file);
  ready.onload = (e) => {
    const re = e.target.result;
    canvasDataURL(re, w, objDiv);
  };
}

/**
 * canvasDataURL 传入URL,生成base64文件
 * @param path url
 * @param obj 压缩等参数
 * @param callback 生成压缩的回调
 */
function canvasDataURL(path, obj, callback) {
  const img = new window.Image();
  img.crossOrigin = 'Anonymous';
  img.onload = () => {
    // 默认按比例压缩
    const w = img.width;
    const h = img.height;
    let newW = 0;
    let newH = 0;
    const scale = w / h;
    if (obj.scale) {
      newW = obj.scale * w;
      newH = newW / scale;
    } else {
      newW = obj.width || w;
      newH = obj.height || newW / scale;
    }
    if (isIos && (newW > 4500 || newH > 4500)) {
    // IOS大部分机型,在像素超过4500状况下,使用canvas.toDataURL直接崩溃
      if (newW > newH) {
        newW = 4500;
        newH = newW / scale;
      } else {
        newH = 4500;
        newW = newH * scale;
      }
    }
    let qualit = 0.7; // 默认图片质量为0.7
    // 生成canvas
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    // 建立属性节点
    const anw = document.createAttribute('width');
    anw.nodeValue = newW;
    const anh = document.createAttribute('height');
    anh.nodeValue = newH;
    canvas.setAttributeNode(anw);
    canvas.setAttributeNode(anh);
    ctx.drawImage(img, 0, 0, newW, newH);
    // 图像质量
    if (obj.quality && obj.quality <= 1 && obj.quality > 0) {
      qualit = obj.quality;
    }
    // quality值越小,所绘制出的图像越模糊
    const base64 = canvas.toDataURL('image/jpeg', qualit);
    // 回调函数返回base64的值
    callback(base64);
  };
  img.src = path;
}

/**
 * 将以base64的图片url数据转换为File或Blob对象
 * @param urlData 用url方式表示的base64图片数据
 * @param fileName 文件名
 */
function convertBase64UrlToFromData(urlData, fileName) {
  const arr = urlData.split(',');
  const mime = arr[0].match(/:(.*?);/)[1];
  const bstr = window.atob(arr[1]);
  let n = bstr.length;
  const u8arr = new Uint8Array(n);
  // eslint-disable-next-line no-plusplus
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  // const blob = new window.Blob([u8arr], { type: mime });
  // blob.lastModifiedDate = new Date();
  // blob.name = 'base64File';
  const file = new window.File([u8arr], fileName || 'base64File', { type: mime });
  // file.lastModifiedDate = new Date();
  // file.name = 'base64File';
  return file;
  // const fd = new window.FormData();
  // fd.append('file', blob, `${Date.now()}.png`);
  // return fd;
}

export {
  convertBase64UrlToFromData,
  photoCompress,
};
复制代码
相关文章
相关标签/搜索