JS 压缩图片简易实现

·  阅读 2789

在日常开发中多多少少会碰到用户上传图片的场景,随着拍照设备的提升,越来越多大尺寸照片诞生,无论是存储空间对于服务器压力,还是传输速率对于用户体验都有着很大的影响。

要把一张图从大变小,马上能想到的就是三步曲:转换格式缩小尺寸降低画质,大多数情况下 转换格式 能达到比较好的效果(如 png 转 jpeg / webp)。

那么,要如何在端上完成图片压缩呢?

通过了解 Canvas 的 API 可以知道,Canvas 可以绘制图片,调整尺寸、区域裁剪、设置图片画质*(仅 jpg、webp)*,最重要的它还可以输出指定格式的图片文件。

简单实现

获取文件

<input /> 选择图片后获取到文件信息,通过 FileReader 来进一步将图片读取成 base64

// ...

inputChanged = (e) => {
  let that = this
  let file = e.target.files[0]

  // 通过 FileReader 读取文件
  let reader = new FileReader()
  reader.readAsDataURL(file)
  // 在读取完成后进行下一步处理
  reader.onload = function (e) {
    // src 是 base64 
    let src = e.target.result
    console.log(src)
    // 下一步要对src进行处理
    that.dealImage(src)
  }
}

render() {
  return (
    <div>
      <input onChange={this.inputChanged} type="file" />
    </div>
  )
}
复制代码

读取图片

通过 Image 对象加载上一步的 base64 图片,然后在图片的 onload 后进行 Canvas 操作

// ...
dealImage = (src) => {
  let that = this
  let image = new Image()
  image.src = src
  image.onload = function () {
    // 通过 Canvas 操作来处理图片
    that.compressImage(image)
  }
}
复制代码

Canvas处理

// ...

compressImage = (image) => {
  // 创建 canvas 节点
  let canvas = document.createElement('canvas')
  // 获取 canvas 操作对象
  let ctx = canvas.getContext('2d')

  // 读取原始图片尺寸
  let imageW = image.width, imageH = image.height
  // 指定输出图片尺寸, 按比例,比如限制宽是1024
  let afterW = 1024, afterH = afterW * imageH / imageW

  // 设置 canvas 画布大小
  canvas.width = imageW
  canvas.height = imageH

  // -----进行处理
  // 不压缩
  // drawImage(image, dx, dy)
  ctx.drawImage(image, 0, 0)

  // 压缩到指定尺寸
  // drawImage(image, dx, dy, dWidth, dHeight)
  ctx.drawImage(image, 0, 0, afterW, afterH)

  // 按位置截取并压缩
  // drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
  ctx.drawImage(image, 20, 30, 50, 60, 0, 0, afterW, afterH);

  // -----输出结果
  // 类型默认png,可选jpeg、webp
  // - 获取处理后的 base64 数据
  let data = canvas.toDataURL('image/jpeg', 0.8)
  console.log(data)

  // - 转成 blob 并在回调中进行下一步操作
  canvas.toBlob(function (blob) {
    // 操作 blob,做上传之类的
    console.log(blob)
  }, 'image/webp', 0.8)
}
复制代码

drawImage

入参形式有以下三种, 具体释义可看 Canvas - drawImage()

  • drawImage(image, dx, dy)
  • drawImage(image, dx, dy, dWidth, dHeight)
  • drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)

结合下图还是能很快理解各个参数含义的

drawImage

获取结果

可以通过 toDataURL(mimeType, quality)toBlob(callback, mimeType, quality) 来获取处理结果 在输出时,可以设置 mineTpye 来转换格式,默认是 png,如果是 jpeg 和 webp 的话还可以设置质量

具体可查阅: Canvas - toDataURL() Canvas - toBlob()

现成方案

除了自己手动撸一个图片压缩处理,当然也有更快更直接的现成方案

上传前压缩图片

使用 compressorjs 可以在上传前对图片进行多种操作以达到压缩图片大小的目的,具体用法可以参阅其 Readme文档

下载压缩图片

国内常用的七牛云存储图片资源,通过了解官方文档 七牛-图片高级处理 ,七牛以直接获取经过 格式转换裁切降画质缩略图旋转 等 操作后的图片。

参考

Canvasapi.cn compressorjs

分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改