canvas实现压缩图片

canvas实现压缩图片

  • 前言
  • 步骤
  • 代码
  • 参考

前言

上传图片对图片大小有要求,故需要前端压缩图片后再上传。简单的实现效果如下:
您可以点击这里:图片压缩
canvas实现压缩图片_第1张图片

步骤

  • 上传一张图片,进行校验,获取图片文件。
  • 使用 FileReaderreadAsDataURL 方法将文件转成 base64 字符串,即图片的 url
  • 使用 canvasdrawImage 方法绘制图片,toDataURL 方法获取 Data Url,即可以实现压缩图片

代码

DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>图片压缩title>
head>
<body>
  <input type="file" name="" id="file">
  <input type="button" value="下载" id="download">
  <div>图片压缩比:<span id="ratio">span>div>
  <script>
    const fileEl = document.querySelector('#file')
    const ratioEl = document.querySelector('#ratio')
    const downloadEl = document.querySelector('#download')
    const canvas = document.createElement('canvas')
    const ctx = canvas.getContext('2d')
    const body = document.body
    // 压缩后的图片url
    let compressUrl = ''
    // 最大上传文件大小
    const MAX_SIZE = 3 * 1024 * 1024
    // 上传文件类型
    const FILE_TYPES = ['image/jpeg', 'image/png']
    // 上传文件最大宽度
    const MAX_WIDTH = 1024
    // 上传文件最大高度
    const MAX_HEIGHT = 1024
    // 上传文件最大宽高比
    const MAX_WH_RATIO = MAX_WIDTH / MAX_HEIGHT
    // 重置
    function resetEl () {
      const imgArr = body.querySelectorAll('img')
      imgArr.forEach(v => {
        body.removeChild(v)
      })
      ratioEl.innerHTML = ''
    }
    // 将文件转成base64
    function convertFile2base64 (file) {
      return new Promise((resolve, reject) => {
        let reader = new FileReader()
        reader.addEventListener('load', e => {
          resolve(e.target.result)
          reader = null
        })
        reader.readAsDataURL(file)
      })
    }
    // 压缩图片
    function compress (url, fileType) {
      const img = new Image()
      img.src = url
      body.appendChild(img)
      img.addEventListener('load', e => {
        const {width: originWidth, height: originHeight} = e.target
        // 原始宽高比
        const originWHRatio = originWidth / originHeight
        let targetWidth = originWidth
        let targetHeight = originHeight
        // 1、计算上传图片压缩后的宽高
        // 2、绘制压缩后的图片
        // 3、上传
        if (originWidth > MAX_WIDTH || originHeight > MAX_HEIGHT) {
          if (originWHRatio > MAX_WH_RATIO) {
            // 图片更宽
            targetWidth = MAX_WIDTH
            targetHeight = Math.round(targetWidth / originWHRatio)
          } else {
            // 图片更高
            targetHeight = MAX_HEIGHT
            targetWidth = Math.round(targetHeight * originWHRatio)
          }
        }
        // 图片压缩比
        const ratio = originWidth / targetWidth
        const newImg = document.createElement('img')
        ratioEl.innerHTML = ratio
        canvas.width = targetWidth
        canvas.height = targetHeight
        ctx.clearRect(0, 0, targetWidth, targetHeight)
        // 绘制压缩的图片
        ctx.drawImage(img, 0, 0, targetWidth, targetHeight)
        // 获取 Data Url
        compressUrl = canvas.toDataURL(fileType);
        newImg.src = compressUrl
        newImg.addEventListener('load', () => {
          body.appendChild(newImg)
        })
        // body.appendChild(canvas)
      })
    }
    fileEl.addEventListener('change', e => {
      resetEl()
      const [file] = e.target.files
      if (!file) return
      const {size: fileSize, type: fileType} = file
      console.warn('file', file, fileSize, MAX_SIZE,  fileType);
      if (!FILE_TYPES.includes(fileType)) {
        alert('只能上传图片')
        fileEl.value = ''
        return
      }
      if (fileSize > MAX_SIZE) {
        alert('图片不能超过3M')
        fileEl.value = ''
        return
      }
      convertFile2base64(file).then(res => {
        compress(res, fileType)
      })
    })
    downloadEl.addEventListener('click', e => {
      const a = document.createElement('a')
      a.href = compressUrl
      a.style.display = 'none'
      a.download = '图片'
      body.appendChild(a)
      a.click()
      a.remove()
    })
  script>
body>
html>

参考

https://www.cnblogs.com/goloving/p/8260206.html
https://www.jianshu.com/p/f46195810c3b

你可能感兴趣的:(前端,canvas,图片压缩,图片上传,img)