欢迎光临
我们一直在努力

使用canvas做图片压缩

简介

当你希望上传图片时在前端展示,并希望像在想后端发送图片前进行压缩,那么可以看一下这一篇文章。

步骤

首先使用原声JS的方式创建input标签:

<input type="file" name="file" id="upload">

然后定义一下基础属性并获取input元素:

const ACCEPT = ['image/png', 'image/jpg', 'image/jpeg']
const MAXSIZE = 3 * 1024 * 1024
const MAXSIZE_STR = '3MB'
const upload = document.getElementById('upload')

添加监听事件,监听input上传图片时执行回调函数,解构赋值获取file,在file下解构赋值获取长度和上传图片片的类型:

upload.addEventListener('change',function(e){
    const [file] = e.target.files
    if(!file){
        return
    }
    const {
        size: fileSize,
        type:fileType
    } = file
})

接下来进行图片类型检查和图片大小检查:

if(!ACCEPT.includes(fileType)){
    // 在这里提醒用户
    upload.value = ''
    return
}
if(fileSize>MAXSIZE){
    // 提醒用户
    upload.value = ''
    return
}

当图片类型和图片大小都符合要求时,我们需要将图片转换成base64格式,获取base64格式可以通过FileReader():

function convertImageToBase64(file,cb){
        let reader = new FileReader()
        reader.addEventListener('load',function(e){
            // e.target.result 就是我们需要的base64字符串
            cb(e.target.result)
        })
        reader.readAsDataURL(file)
}

在获取到base64字符串后,我们就可以执行图片压缩的操作了,压缩图片我们需要用到canvas,在此之前我们应当获取图片的尺寸,并判断是否要更改尺寸到我们想要的目标大小:

function compress(base64Img, cb) {
  let maxW = 540
  let maxH = 540
  const image = new Image()
  image.addEventListener('load', function () {
    let ratio //压缩比
    let needCompress = false // 是否需要压缩
    if (maxW < image.naturalWidth) {
      needCompress = true
      ratio = image.naturalWidth / maxW
      maxH = image.naturalHeight / ratio
    }
    if (maxH < image.naturalHeight) {
      needCompress = true
      ratio = image.naturalHeight / maxH
      maxW = image.naturalWidth / ratio
    }
    if (!needCompress) {
      maxW = image.naturalWidth
      maxH = image.naturalHeight
    }
    // 下面通过canvas压缩图片
    const canvas = document.createElement('canvas')
    canvas.setAttribute('id', '__compress__')
    canvas.width = maxW
    canvas.height = maxH
    canvas.style.visibility = 'hidden'
    document.body.append(canvas)

    const ctx = canvas.getContext('2d')
    ctx.clearRect(0, 0, maxW, maxH)
    ctx.drawImage(image, 0, 0, maxW, maxH)
    //👇压缩图片比例 返回的compressImage就是压缩后的base64字符串
    const compressImage = canvas.toDataURL('image/jpeg', 0.8) 
    //👇的回调函数可以调用服务器上传函数
    cb(compressImage)
    const _image = new Image();
    _image.src = compressImage
    document.body.appendChild(_image)
    canvas.remove() // 移除canvas
  })
  image.src = base64Img
  document.body.appendChild(image)
}

完整代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <input type="file" name="file" id="upload">
  <script>
    const ACCEPT = ['image/png', 'image/jpg', 'image/jpeg']
    const MAXSIZE = 3 * 1024 * 1024
    const MAXSIZE_STR = '3MB'
    const upload = document.getElementById('upload')

    upload.addEventListener('change', function (e) {
      const [file] = e.target.files
      if (!file) {
        return
      }
      const {
        size: fileSize,
        type: fileType
      } = file

      // 图片支持类型检查
      if (!ACCEPT.includes(fileType)) {
        console.log(`不支持${fileType.split('/')}类型的文件!`);
        upload.value = ''
        return
      }
      // 图片大小检查
      if (fileSize > MAXSIZE) {
        console.log(`文件超出规定的${MAXSIZE_STR}大小`);
        upload.value = ''
        return
      }
      convertImageToBase64(file, compress);

      // 获取base64
      function convertImageToBase64(file, cb) {
        let reader = new FileReader()
        console.log(reader);
        reader.addEventListener('load', function (e) {
          cb(e.target.result, uploadImage)
        })
        reader.readAsDataURL(file)
      }
      // 图片压缩
      function compress(base64Img, cb) {
        let maxW = 540
        let maxH = 540
        const image = new Image()
        image.addEventListener('load', function () {
          let ratio //压缩比
          let needCompress = false // 是否需要压缩
          if (maxW < image.naturalWidth) {
            needCompress = true
            ratio = image.naturalWidth / maxW
            maxH = image.naturalHeight / ratio
          }
          if (maxH < image.naturalHeight) {
            needCompress = true
            ratio = image.naturalHeight / maxH
            maxW = image.naturalWidth / ratio
          }
          if (!needCompress) {
            maxW = image.naturalWidth
            maxH = image.naturalHeight
          }
          const canvas = document.createElement('canvas')
          canvas.setAttribute('id', '__compress__')
          canvas.width = maxW
          canvas.height = maxH
          canvas.style.visibility = 'hidden'
          document.body.append(canvas)

          const ctx = canvas.getContext('2d')
          ctx.clearRect(0, 0, maxW, maxH)
          ctx.drawImage(image, 0, 0, maxW, maxH)
          const compressImage = canvas.toDataURL('image/jpeg', 0.8) //压缩图片比例
          cb(compressImage)
          const _image = new Image();
          _image.src = compressImage
          document.body.appendChild(_image)
          canvas.remove() // 移除canvas
        })
        image.src = base64Img
        document.body.appendChild(image)
      }

      // 上传图片到服务器
      function uploadImage(compressBase64Img) {
        console.log('拿到了...' + compressBase64Img)
      }
    })
  </script>
</body>

</html>
赞(1) 打赏
未经允许不得转载:散人研 » 使用canvas做图片压缩
分享到: 更多 (0)

评论 抢沙发

7 + 3 =
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏