vue+elementui+web上传图片压缩

注意事项:未解决PNG带通道透明图片压缩后黑屏的问题,网上有评论说绘制背景色白色

context.fillStyle = '#fff'

个人觉得意义不大,因为只要是做设计的都明白透明通道和白色背景不是同一个概念。
为啥不支持PNG?
点击此处查看原因

原因总结:会用到toDataURL('image/jpeg',qualitys)的一个方法

在指定图片格式为 image/jpeg 或 image/webp的情况下,可以从 0 到 1 的区间内选择图片的质量。如果超出取值范围,将会使用默认值 0.92,其他参数会被忽略。
文件工具:compress.js

export default {
  compressImg: function(file, quality) {
    var qualitys = 0.52
    // console.log(parseInt((file.size / 1024).toFixed(2)))
    if (parseInt((file.size / 1024).toFixed(2)) < 1024) {
      qualitys = 0.85
    }
    if (5 * 1024 < parseInt((file.size / 1024).toFixed(2))) {
      qualitys = 0.92
    }
    if (quality) {
      qualitys = quality
    }
    if (file[0]) {
      return Promise.all(
        Array.from(file).map(e => this.compressImg(e, qualitys))
      ) // 如果是 file 数组返回 Promise 数组
    } else {
      return new Promise(resolve => {
        // console.log(file)
        if ((file.size / 1024).toFixed(2) < 300) {
          resolve({
            file: file
          })
        } else {
          const reader = new FileReader() // 创建 FileReader
          reader.onload = ({ target: { result: src } }) => {
            const image = new Image() // 创建 img 元素
            image.onload = async () => {
              const canvas = document.createElement('canvas') // 创建 canvas 元素
              const context = canvas.getContext('2d')
              var targetWidth = image.width
              var targetHeight = image.height
              var originWidth = image.width
              var originHeight = image.height
              if (
                1 * 1024 <= parseInt((file.size / 1024).toFixed(2)) &&
                parseInt((file.size / 1024).toFixed(2)) <= 10 * 1024
              ) {
                var maxWidth = 1600
                var maxHeight = 1600
                targetWidth = originWidth
                targetHeight = originHeight
                // 图片尺寸超过的限制
                if (originWidth > maxWidth || originHeight > maxHeight) {
                  if (originWidth / originHeight > maxWidth / maxHeight) {
                    // 更宽,按照宽度限定尺寸
                    targetWidth = maxWidth
                    targetHeight = Math.round(
                      maxWidth * (originHeight / originWidth)
                    )
                  } else {
                    targetHeight = maxHeight
                    targetWidth = Math.round(
                      maxHeight * (originWidth / originHeight)
                    )
                  }
                }
              }
              if (
                10 * 1024 <= parseInt((file.size / 1024).toFixed(2)) &&
                parseInt((file.size / 1024).toFixed(2)) <= 20 * 1024
              ) {
                maxWidth = 1400
                maxHeight = 1400
                targetWidth = originWidth
                targetHeight = originHeight
                // 图片尺寸超过的限制
                if (originWidth > maxWidth || originHeight > maxHeight) {
                  if (originWidth / originHeight > maxWidth / maxHeight) {
                    // 更宽,按照宽度限定尺寸
                    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.fillStyle = '#fff'
              context.drawImage(image, 0, 0, targetWidth, targetHeight) // 绘制 canvas
              
              const canvasURL = canvas.toDataURL('image/jpeg', qualitys)
              const buffer = atob(canvasURL.split(',')[1])
              let length = buffer.length
              const bufferArray = new Uint8Array(new ArrayBuffer(length))
              while (length--) {
                bufferArray[length] = buffer.charCodeAt(length)
              }
              const miniFile = new File([bufferArray], file.name, {
                type: 'image/jpeg'
              })
              console.log({
                file: miniFile,
                origin: file,
                beforeSrc: src,
                afterSrc: canvasURL,
                beforeKB: Number((file.size / 1024).toFixed(2)),
                afterKB: Number((miniFile.size / 1024).toFixed(2)),
                qualitys: qualitys
              })
              resolve({
                file: miniFile,
                origin: file,
                beforeSrc: src,
                afterSrc: canvasURL,
                beforeKB: Number((file.size / 1024).toFixed(2)),
                afterKB: Number((miniFile.size / 1024).toFixed(2))
              })
            }
            image.src = src
          }
          reader.readAsDataURL(file)
        }
      })
    }
  }
}

上述工具返回的是一个promise对象.
在你封装好的的uploader.vue组件中使用

import Compress from '@/utilities/compress.js'

关键点:因为异步的原因,我们无法在elementui 上传组件的 beforeUpload()方法中使用,必须使用自定义的方法上传,覆盖掉组件的上传方法





额外记录,与当前文章无关

// violet.js
export const OSS_URL = (parameters) => {
  return fetch({
    cloud: 'Violet',
    url: '/security/upload/temporary',
    method: 'post',
    data: parameters,
  })
}
//fetch.js
  headers: {
    'X-Requested-With': 'XMLHttpRequest',
    // 'Content-Type': 'application/json; charset=utf-8',
    'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundary5J9Z4y1jAznANNwp',
  }
if (config.method === 'post') {
      //config.data = JSON.stringify(config.data)
      const formdata = new FormData()
      formdata.append('cloud', 'violet'),
      formdata.append('micro', 'agiles'),
      formdata.append('file', config.data.file),
      config.data=formdata
    }
//demandAdd.vue
:fileSize=20 

你可能感兴趣的:(vue+elementui+web上传图片压缩)