美文网首页Web前端之路web前端常用js小段代码图片压缩解决方案
前端的图片压缩image-compressor(可在图片上传前实

前端的图片压缩image-compressor(可在图片上传前实

作者: 侬姝沁儿 | 来源:发表于2018-04-17 16:07 被阅读53次

    image-compressor

    一个简单的JavaScript图像压缩器。使用浏览器的原生canvas.toBlob API做的压缩工作。一般使用此压缩是在客户端图像文件上传之前。

    实例模板:Website
    github:image-compressor

    Getting started(新手入门)

    Install(npm 安装)

    npm install image-compressor.js // 注意是image-compressor.js 不是 image-compressor那是另一个包
    

    Usage(使用)

    Syntax语法
    new ImageCompressor([file[, options]])
    
    参数说明

    file:(可选)压缩的目标图像文件,类型是 File 或者 Blob
    options:(可选)压缩选项,类型是 Object

    案例

    <input type="file" id="file" accept="image/*">
    
    import axios from 'axios'
    import ImageCompressor from 'image-compressor.js' // 引入
    
    document.getElementById('file').addEventListener('change', (e) => {
      const file = e.target.files[0]; // file对象
      if (!file) { return } // 为空处理
      new ImageCompressor(file, {
        quality: .6,
        success(result) {
          const formData = new FormData(); // FormData学习地址 https://developer.mozilla.org/zh-CN/docs/Web/API/FormData
          formData.append('file', result, result.name);
    
          // 通过XMLHttpRequest服务发送压缩的图像文件-Send the compressed image file to server with XMLHttpRequest.
          axios.post('/path/to/upload', formData).then(() => {
            console.log('Upload success');
          });
        },
        error(e) {
          console.log(e.message);
        },
      });
    });
    

    Options参数

    checkOrientation

    是否检查图片的 orientation 属性,类型是 boolean。默认值是 true。

    提示:如果读取图像的EXIF的 orientation 属性(JPEG图像),有可能根据 orientation 属性自动翻转或旋转图像。
    注意:不要一直相信这一点,因为一些JPEG图像有不正确的(不是标准的) orientation 属性

    maxWidth

    输出图像的最大宽度,类型是 number。默认值是 Infinity。值应该大于0。

    因为一个canvas元素的大小限制,所以为了避免得到一个空白的输出图像,你可能需要给最大宽度和最大高度选项设置有限的数字。

    maxHeight

    输出图像的最大高度,类型是 number。默认值是 Infinity。值应该大于0。

    minWidth

    输出图像的最小宽度,类型是 number。默认值是 0。该值应大于0且不应大于maxWidth

    minHeight

    输出图像的最小宽度,类型是 number。默认值是 0。该值应大于0且不应大于maxHeight

    width

    输出图像的宽度,类型是 number。默认值是 undefined。值应该大于0。

    如果没有指定,将使用原始图像的自然宽度,或者如果设置高度选项,则宽度将由自然长宽比自动计算。

    height

    输出图像的高度,类型是 number。默认值是 undefined。值应该大于0。

    如果没有指定,将使用原始图像的自然高度,或者如果设置宽度选项,则高度将由自然长宽比自动计算。
    注意:为了保持与原始图像相同的宽高比,如果设置宽度选项,将使用它自动计算高度,这意味着高度选项将被忽略。

    quality

    输出图像的画质,类型是 number。默认值是 undefined。值是0到1之间的数字。

    小心使用1,因为它可能使输出图像的尺寸变大。
    注意:此选项仅适用于 JPEG 和 WebP 格式的图像。

    Examples:

    图片原来大小 图片压缩大小 压缩比例 描述
    0 2.12MB 114.61 KB 94.72% -
    0.2 2.12MB 349.57 KB 83.90% -
    0.4 2.12MB 517.10 KB 76.18% -
    0.6 2.12MB 694.99 KB 67.99% 推荐
    0.8 2.12MB 1.14 MB 46.41% 推荐
    1 2.12MB 2.12 MB 0% 不推荐
    NaN 2.12MB 2.01 MB 5.02% -

    mimeType

    输出图像的文件类型,类型是 string。默认值是 auto。默认情况下,源映像文件的原始MIME类型将被使用。

    convertSize

    输出图像的文件类型,类型是 number。默认值是 5000000 (5MB)。

    PNG文件超过此值将被转换为JPEG格式。若要禁用此功能,只需将值设置为无穷大。

    Examples (in Chrome 61):

    convertSize 输入的文件大小Input size (type) 输出的文件大小Output size (type) 压缩比
    5 MB 1.87 MB (PNG) 1.87 MB (PNG) 0%
    5 MB 5.66 MB (PNG) 450.24 KB (JPEG) 92.23%
    5 MB 9.74 MB (PNG) 883.89 KB (JPEG) 91.14%

    beforeDraw(context, canvas)

    在将图像绘制到画布中进行压缩之前,要执行的钩子函数,类型是 Function。默认值是 null。
    参数说明:

    context: canvas的2D渲染上下文。
    canvas: 压缩画布

    new ImageCompressor(file, {
      beforeDraw(context) {
        context.fillStyle = '#fff';
      },
    });
    

    drew(context, canvas)

    该钩子函数执行后,将图像绘制到画布中进行压缩,类型是 Function。默认值是 null。
    参数说明:

    context: canvas的2D渲染上下文。
    canvas: 压缩画布

    new ImageCompressor(file, {
      drew(context) {
        context.filter = grayscale(100%);
      },
    });
    

    success(result)

    成功压缩图像时执行的钩子函数,类型是 Function。默认值是 null。
    参数说明:

    result: 压缩后的图像(一个Blob对象)。

    error(err)

    当图像压缩失败时执行的钩子函数,类型是 Function。默认值是 null。
    参数说明:

    err: 压缩错误(一个Error对象)。

    方法

    compress(file[, options])

    file:(必选)压缩的目标图像文件,类型是 File 或者 Blob
    options:(可选)压缩选项,类型是 Object
    返回值: Promise

    使用:

    const imageCompressor = new ImageCompressor();
    
    imageCompressor.compress(e.target.files[0], {
        quality: 0.8,
        maxHeight: 1000,
        maxWidth: 1000
    }).then((result) => { // 压缩成功的回调 Handle the compressed image file.
        const formData = new FormData()
        formData.append('file', result)
        // 请求:Send the compressed image file to server with XMLHttpRequest...
        // var xhr = new XMLHttpRequest()
        // xhr.withCredentials = true...
    }).catch((err) => { // 压缩失败的回调 Handle the error
        console.log(err)
    })
    

    浏览器支持

    • Chrome (latest)
    • Firefox (latest)
    • Safari (latest)
    • Opera (latest)
    • Edge (latest)
    • Internet Explorer 10+ (requires a Promise polyfill as es6-promise)

    案例

    基于vue的element-ui图片上传前的压缩,注意是element-ui的上传组件。

    首先:

    npm install image-compressor.js
    

    然后:

    import ImageCompressor from 'image-compressor.js' // 引入图片压缩
    

    构写代码:

    html

    <el-upload  :httpRequest="httpRequest"></el-upload>
    

    httpRequest

    httpRequest (options) { // 覆盖默认的上传行为,可以自定义上传的实现,解决压缩问题
      if (this.imageCompress && this.acceptName === 'image/*') { // 如果允许压缩,并且当前上传的是图片
        var imageCompressor = new ImageCompressor() // 压缩成功则使用压缩的结果,不成功直接上传
        imageCompressor.compress(options.file, {
          quality: 0.8,
          maxHeight: 1000,
          maxWidth: 1000
        }).then((result) => { // 压缩成功的回调
          options.file = result
          console.log(options)
          return ajax(options) // 压缩成功把压缩成功的数据传递给ajax.js
        }).catch((err) => { // 压缩失败的回调
          console.log(err)
          return options.file // 压缩失败把原文件传递
        })
      } else {
        return ajax(options)
      }
    }
    

    ajax.js

    使用说明:ajax.js可以拿出来单独使用哟!如果需要封装成引用型组件,请自行封装。

    function getError (action, option, xhr) {
      let msg
      if (xhr.response) {
        msg = `${xhr.response.error || xhr.response}`
      } else if (xhr.responseText) {
        msg = `${xhr.responseText}`
      } else {
        msg = `fail to post ${action} ${xhr.status}`
      }
    
      const err = new Error(msg)
      err.status = xhr.status
      err.method = 'post'
      err.url = action
      return err
    }
    
    function getBody (xhr) {
      const text = xhr.responseText || xhr.response
      if (!text) {
        return text
      }
    
      try {
        return JSON.parse(text)
      } catch (e) {
        return text
      }
    }
    
    export default function upload (option) {
      if (typeof XMLHttpRequest === 'undefined') {
        return
      }
    
      const xhr = new XMLHttpRequest()
      const action = option.action
    
      if (xhr.upload) {
        xhr.upload.onprogress = function progress (e) {
          if (e.total > 0) {
            e.percent = e.loaded / e.total * 100
          }
          option.onProgress(e)
        }
      }
    
      const formData = new FormData()
    
      if (option.data) {
        Object.keys(option.data).forEach(key => {
          formData.append(key, option.data[key])
        })
      }
    
      formData.append(option.filename, option.file)
    
      xhr.onerror = function error (e) {
        option.onError(e)
      }
    
      xhr.onload = function onload () {
        if (xhr.status < 200 || xhr.status >= 300) {
          return option.onError(getError(action, option, xhr))
        }
    
        option.onSuccess(getBody(xhr))
      }
    
      xhr.open('post', action, true)
    
      if (option.withCredentials && 'withCredentials' in xhr) {
        xhr.withCredentials = true
      }
    
      const headers = option.headers || {}
    
      for (let item in headers) {
        if (headers.hasOwnProperty(item) && headers[item] !== null) {
          xhr.setRequestHeader(item, headers[item])
        }
      }
      xhr.send(formData)
      return xhr
    }
    
    

    结语

    到此我们学会了使用image-compressor.js进行图片压缩,并且可以根据image-compressor.js在图片上传前实现图片压缩。

    提示:后面还有精彩敬请期待,请大家关注我的专题:web前端。如有意见可以进行评论,每一条评论我都会认真对待。

    相关文章

      网友评论

        本文标题:前端的图片压缩image-compressor(可在图片上传前实

        本文链接:https://www.haomeiwen.com/subject/nzcpkftx.html