2020-05-23 前端图片压缩

2020-05-23  本文已影响0人  FConfidence

前端完成图片压缩

流程

  1. 通过原生的input标签拿到要上传的图片文件
  2. 将图片文件转化成img元素标签
  3. 在canvas上压缩绘制该HTMLImageElement
  4. 将canvas绘制的图像转成blob文件
  5. 最后将该blob文件传到服务端

1. 使用Input标签来获取图片文件资源

<input type="file" accept="image/*" />

2. 读取文件转成img标签元素

// 先new一个img和fileReader的实例
const img = new Image()
const reader = new FileReader()// 读取文件资源
reader.readAsDataURL(file)

reader.onload = function(e) {
  img.src = e.target.result
}

3. canvas压缩,核心步骤

const { width: originWidth, height: originHeight } = img;

// 最大尺寸限制
const maxWidth = 1000, maxHeihgt = 1000;

// 需要压缩的目标尺寸
let targetWidth = originWidth, targetHeight = originHeight

// 等比例计算超过最大限制时缩放后的图片尺寸
if (originWidth > maxWidth || originHeight > maxHeight) {
  if (originWidth / originHeight > 1) {
   // 宽图片
   targetWidth = maxWidth
   targetHeight = Math.round(maxWidth * (originHeight / originWidth))
  } else {
   // 高图片
   targetHeight = maxHeight
   targetWidth = Math.round(maxHeight * (originWidth / originHeight))
  }
 }

计算好将要压缩的尺寸后,创建canvas实例,设置canvas的宽高度为压缩计算后的尺寸,并将img绘制到上面

// 创建画布
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
 
// 设置宽高度为等同于要压缩图片的尺寸
canvas.width = targetWidth
canvas.height = targetHeight
context.clearRect(0, 0, targetWidth, targetHeight)

//将img绘制到画布上
context.drawImage(img, 0, 0, targetWidth, targetHeight)

4. 转成blob文件

canvas.toBlob(callback, type, encoderOptions);

5. 将blob上传,大功告成


// 压缩前将file转换成img对象
function readImg(file) {
 return new Promise((resolve, reject) => {
  const img = new Image();
  const reader = new FileReader();
  reader.onload = function(e) {
   img.src = e.target.result
  };
  reader.onerror = function(e) {
   reject(e)
  };
  // 读取文件, 执行回调
  reader.readAsDataURL(file)

  // 图片加载完成, 执行
  img.onload = function() {
   resolve(img)
  }
  img.onerror = function(e) {
   reject(e)
  }
 })
}

/**
 * 压缩图片
 * @param img 被压缩的img对象
 * @param type 压缩后转换的文件类型
 * @param mx 触发压缩的图片最大宽度限制
 * @param mh 触发压缩的图片最大高度限制
 */
function compressImg(img, type, mx, mh) {
 return new Promise((resolve, reject) => {
  const canvas = document.createElement('canvas')
  const context = canvas.getContext('2d')
  const { width: originWidth, height: originHeight } = img
  // 最大尺寸限制
  const maxWidth = mx
  const maxHeight = mh
  // 目标尺寸
  let targetWidth = originWidth
  let targetHeight = originHeight
  if (originWidth > maxWidth || originHeight > maxHeight) {
   if (originWidth / originHeight > 1) {
    // 宽图片
    targetWidth = maxWidth
    targetHeight = Math.round(maxWidth * (originHeight / originWidth))
   } else {
    // 高图片
    targetHeight = maxHeight
    targetWidth = Math.round(maxHeight * (originWidth / originHeight))
   }
  }
  canvas.width = targetWidth
  canvas.height = targetHeight
  context.clearRect(0, 0, targetWidth, targetHeight)
  // 图片绘制
  context.drawImage(img, 0, 0, targetWidth, targetHeight)
  canvas.toBlob(function(blob) {
   resolve(blob)
  }, type || 'image/png') })
}

// 文件上传
async function upload(file){
  const img = await readImg(file)
  const blob = await compressImg(img, file.type, 1000, 1000)
  const formData = new FormData()
  formData.append('file', blob, 'xxx.jpg')
  axios.post('http://xxx.com/api',formData)
}
upload(file).catch(e => console.log(e))
上一篇 下一篇

猜你喜欢

热点阅读