图片上传和canvas压缩的方法介绍(流程)-kb88凯时官网登录

时间:2020-09-30
阅读:
免费资源网,https://freexyz.cn/

我们通常在做图片上传的时候都会遇上这样的情况,一是后端接口限制上传图片的大小,或者是即使后端没有限制大小,因为图片太大在前端渲染时太慢,造成页面加载体验较差。因此我们很有必要对上传的图片进行压缩。

本文在gitthub做了收录:https://github.com/michael-lzg/my--article/blob/master/other/canvas压缩图片.md

本文主要包括以下流程:

  • 用户通过 input 框选择图片
  • 使用 filereader 进行图片预览
  • 将图片绘制到 canvas 画布上
  • 使用 canvas 画布的能力进行图片压缩
  • 将压缩后的 base64(dataurl) 格式的数据转换成 blob 对象进行上传

input 标签来获取图片

通过设置 input 标签的 type 属性为 file,来让用户可以选择文件,设置 accept 限制选择的文件类型,绑定 onchange 事件,来获取确认选择后的文件

 


filereader

filereader 是什么,我们先来看看官方文档的介绍

filereader 对象允许 web 应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 file 或 blob 对象指定要读取的文件或数据。

filereader 常用的两个方法如下:

  • filereader.onload:处理 load 事件。即该钩子在读取操作完成时触发,通过该钩子函数可以完成例如读取完图片后进行预览的操作,或读取完图片后对图片内容进行二次处理等操作。
  • filereader.readasdataurl:读取方法,并且读取完成后,result 属性将返回 data url 格式(base64 编码)的字符串,代表图片内容。

在图片上传中,我们可以通过 readasdata 方法进行了文件的读取,并且通过 result 属性拿到了图片的 base64(dataurl) 格式的数据,然后通过该数据实现了图片预览的功能

 

canvas 压缩图片

这是图片上传压缩的核心所在,我们先使用 canvasrenderingcontext2d.drawimage() 方法将上传的图片文件在画布上绘制出来,再使用 canvas.todata 将画布上的图片信息转换成 base64(dataurl) 格式的数据。

drawimage()

drawimage() 方法在画布上绘制图像、画布或视频。drawimage() 方法也能够绘制图像的某些部分,以及/或者增加或减少图像的尺寸。参数如下

  • img 规定要使用的图像、画布或视频。
  • sx 可选。开始剪切的 x 坐标位置。
  • sy 可选。开始剪切的 y 坐标位置。
  • swidth 可选。被剪切图像的宽度。
  • sheight 可选。被剪切图像的高度。
  • x 在画布上放置图像的 x 坐标位置。
  • y 在画布上放置图像的 y 坐标位置。
  • width 可选。要使用的图像的宽度。(伸展或缩小图像)
  • height 可选。要使用的图像的高度。(伸展或缩小图像)

 

var cas = document.queryselector('canvas')
var ctx = cas.getcontext('2d')
// 先创建图片对象
var img = new image()
img.src = './images/1.jpg'
// 图片加载完之后
img.onload = function () {
  ctx.drawimage(img, 206, 111, 32, 38, 100, 100, 32, 38)
}

canvas.todata

canvas.todata 方法可以将 canvas 画布上的信息转换为 base64(dataurl) 格式的图像信息,纯字符的图片表示形式。该方法接收 2 个参数:

  • mimetype(可选): 表示需要转换的图像的 mimetype 类型。默认值是 image/png,还可以是 image/jpeg, image/webp 等。
  • quailty(可选):quality 表示转换的图片质量。范围是 0 到 1。图片的 mimetype 需要是 image/jpeg 或者 image/webp,其他 mimetype 值无效。默认压缩质量是 0.92。

 

var canvas = document.createelement('canvas')
canvas.todata

到这里,我们先来上 canvas 压缩图片的代码

 

function compress(base64, quality, mimetype) {
  let canvas = document.createelement('canvas')
  let img = document.createelement('img')
  img.crossorigin = 'anonymous'
  return new promise((resolve, reject) => {
    img.src = base64
    img.onload = () => {
      let targetwidth, targetheight
      if (img.width > max_width) {
        targetwidth = max_width
        targetheight = (img.height * max_width) / img.width
      } else {
        targetwidth = img.width
        targetheight = img.height
      }
      canvas.width = targetwidth
      canvas.height = targetheight
      let ctx = canvas.getcontext('2d')
      ctx.clearrect(0, 0, targetwidth, targetheight) // 清除画布
      ctx.drawimage(img, 0, 0, canvas.width, canvas.height)
      let imagedata = canvas.todata
      resolve(imagedata)
    }
  })
}

将 base64 转化为文件

  • 通过 window.atob 将 base-64 字符串解码为 binarystring(二进制文本);
  • 将 binarystring 构造为 multipart/form-data 格式;
  • 用 uint8array 将 multipart 格式的二进制文本转换为 arraybuffer

 

function dataurltoblob(base64, mimetype) {
  let bytes = window.atob(base64.split(',')[1])
  let ab = new arraybuffer(bytes.length)
  let ia = new uint8array(ab)
  for (let i = 0; i < bytes.length; i  ) {
    ia[i] = bytes.charcodeat(i)
  }
  return new blob([ab], { type: mimetype })
}

将图片上传到服务端

  • 创建一个 formdata,把 blob append 到 formdata 里面
  • 请求服务端接口,提交图片

 

function uploadfile(url, blob) {
  let formdata = new formdata()
  let request = new xmlhttprequest()
  formdata.append('image', blob)
  request.open('post', url, true)
  request.send(formdata)
}

ps:在实际开发中,我们要不要把图片转化为 formdata 形式上传到服务端,这就看具体的业务需要了。我们可以上图片上传到腾讯云,直接返回一个'https.xxx.jgp'的图片 url 用于上传。

本文转载自:https://segmentfault.com/a/1190000022891640

免费资源网,https://freexyz.cn/
返回顶部
顶部
网站地图