js canvas 前端实现修改图片尺寸压缩图片大小

阅读 (871)
HTML5 <canvas> 元素用于图形的绘制,通过JavaScript将图片文件内容绘制到画布上,并修改图片宽高尺寸,导出文件二进制流

函数1:读取图片信息(主要是原使图片宽高)

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)
      }
  })
}

函数2:修改图片尺寸(如原图宽高尺寸2000*3000,现在手机拍照像素都很高,照片都在2-5兆,甚至更多大,此时我们将图片宽高尺寸修改到1000*1500,再保存图片,那图片大小肯定就小了)

关于canvas.toBlob(callback, type, encoderOptions);

官方描述:

/**
  * 压缩图片
  * @param img 被压缩的img对象
  * @param type 压缩后转换的文件类型
  * @param mx 触发压缩的图片最大宽度限制
  * @param mh 触发压缩的图片最大高度限制
  */
  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
      // 只有宽高都超标时才按窄边压缩 (可以按自己需求修改判断条件,如果在调用前就判断了,那这里就不用判断 originWidth > maxWidth && originHeight > maxHeight,也可以改成 || 条件,看自己需求)
      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)
      // 转成blob, canvas  toBlob函数有3个参数,第三个参数官方描述:Number类型,值在0与1之间,当请求图片格式为image/jpeg或者image/webp时用来指定图片展示质量。如果这个参数的值不在指定类型与范围之内,则使用默认值,其余参数将被忽略。
      // 简单点说就是修改图片展示质量,如果设置成0.1,那图片质量会压缩的很差,一般在0.8以上可以保证图片在肉眼识别范围不失真,如果对图片质量有要修,只想修改图片宽高尺寸,那建议使用1,默认是0.92,会压缩一点点
      canvas.toBlob(function(blob) {
        resolve(blob)
      }, type || 'image/jpeg')
    })
  }

函数使用,例如我是在React中使用的,这里需要用到 async 和 await 关键词

async fileChange () {
    console.log(this.fileInput)
    // ref获取文件对象
    var file = this.fileInput.files[0]
    console.log(file.size) // 测试打印原文件大小
    const formData = new FormData()
    const maxWidth = 1000 // 设置目标图片最大宽
    const maxHeight = 1000 // 设置目标图片最大高

    const img = await this.readImg(file)
    const { width: originWidth, height: originHeight } = img
    // 宽高都超标,则压缩窄边,否则直接用上传的图片(这里是我业务需求的条件判断,可以按自己需求修改)
    if (originWidth > maxWidth && originHeight > maxHeight) {
      const blob = await this.compressImg(img, file.type, maxWidth, maxHeight)
      formData.append('localImage', blob)
      console.log('blob.size', blob.size) // 测试打印压缩后的大小
    } else {
      formData.append('localImage', file)
    }

    // 这里改成你自己上传文件的逻辑
    Api.uploadFile('/app?api=uploadImage', formData, res => {
      this.setState({
        src: res.data
      })
    })
}

 

更新于:2020-04-08 10:36:24

留言

发表评论

标记为*的字段是必填项(邮箱地址不会被公开), 由于国内舆论控制, 评论需要管理员审核通过方可展示

返回顶部