> 文档中心 > JS图片压缩

JS图片压缩

注意:本文中图片压缩方法只能将压缩后的图片固定保存为 “image/jpeg” 格式,不能设置为 “image/png” 格式(该格式压缩无效)。

具体代码如下

压缩相关的方法:

/** * 文件转base64 * @param {File} file 需要转换的文件 * @param {Function} callback 回调函数, 执行回调后返回 base64 格式图片 */export function imageToBase64(file, callback) {  const reader = new FileReader()  reader.readAsDataURL(file) // 文件转base64  reader.addEventListener('load', e => {    callback && callback(e.target.result)  })}/** * base64 类型转 Blob 类型 * @param {base64} base64 * @returns {Blob} blob */export function base64ToBlob(base64) {  let arr = base64.split(','),    mime = arr[0].match(/:(.*?);/)[1],    bstr = atob(arr[1]),    n = bstr.length,    u8arr = new Uint8Array(n)  while (n--) {    u8arr[n] = bstr.charCodeAt(n)  }  return new Blob([u8arr], { type: mime })}/** * 压缩图片 * @param {base64} originalImage 转换为 base64 的原始图片 * @param {Number} compressRatio 压缩比例 0 - 1, 1则不压缩 * @param {Function} callback 回调方法, 执行回调后返回 base64 格式图片 */export function compressImg(originalImage, compressRatio = 1, callback) {  const image = new Image()  image.src = originalImage  /* 监听图片的load事件 */  image.addEventListener('load', function() {    let [sizeRatio, maxWidth, maxHeight] = [0, 1024, 1024] // 图片压缩宽高比例和最大宽高    let [imageWidth, imageHeight] = [this.naturalWidth, this.naturalHeight] // 图片实际宽高    let compressFlag = false // 图片是否需要压缩    // 如果图片宽度大于最大宽度就等比压缩图片的高度    if (imageWidth > maxWidth) {      compressFlag = true      sizeRatio = imageWidth / maxWidth      maxHeight = imageHeight / sizeRatio    }    // 如果图片高度大于最大高度就等比压缩图片的宽度    if (imageHeight > maxHeight) {      compressFlag = true      sizeRatio = imageHeight / maxHeight      maxWidth = imageWidth / sizeRatio    }    // 如果不需要压缩    if (!compressFlag) {      maxWidth = imageWidth      maxHeight = imageHeight    }    // 使用canvas压缩图片    const canvas = document.createElement('canvas')    const ctx = canvas.getContext('2d')    canvas.setAttribute('id', 'canvas')    canvas.width = maxWidth    canvas.height = maxHeight    ctx.clearRect(0, 0, maxWidth, maxHeight) // 清除画布内所有像素    ctx.drawImage(image, 0, 0, maxWidth, maxHeight) // canvas绘制当前图片    const compressImage = canvas.toDataURL('image/jpeg', compressRatio) // 设置压缩类型和压缩比例获取压缩后的文件, 为 base64    callback && callback(compressImage)  })}

业务中使用,我这里用的 vue,这里只展示了部分代码(大家只需关注 isCompressImg 方法)

beforeRead(file) {  if (file.type !== 'image/jpeg' && file.type !== 'image/png') {    this.$toast('请上传 jpg 或 png 格式图片')    return false  }  return true},afterRead(file) {  file.status = 'uploading'  file.message = '上传中...'  this.btnDisabled = true  const imgFile = file.file  this.isCompressImg(imgFile, img => {    // 此时可以自行将文件上传至服务器    alyOSS      .ossUploadFile({ file: img })      .then(res => { this.fileList = [   {     url: res.url   } ] file.status = 'done' file.message = ''      })      .catch(() => { file.status = 'failed' file.message = '上传失败'      })      .finally(() => { this.btnDisabled = false      })  })},// 判断是否需要压缩isCompressImg(file, callback) {  const maxSize = 1 * 1024 * 1024 // 最大 1M  // 压缩图片  if (file.size > maxSize) {    imageToBase64(file, originalImage => {      compressImg(originalImage, 0.5, compressImage => { // base64 转 blob, blob 再转 file const img = new File([base64ToBlob(compressImage)], file.name, {   type: file.type }) // 递归判断, 防止压缩后的图片仍然大于 1M this.isCompressImg(img, f => {   callback(f) })      })    })  } else {    callback(file)  }}