浅析图片上传及canvas压缩的流程


Posted in HTML / CSS onJune 10, 2020

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

本文在gitthub做了收录:github.com/Michael-lzg…

本文主要包括以下流程:

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

Input 标签来获取图片

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

<input type="file" accept="image/*" onchange="loadFile(event)"

FileReader

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

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

FileReader常用的两个方法如下:

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

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

<div class="container">
  <input type="file" accept="image/*" onchange="loadFile(event)" />
</div>
<script>
  const loadFile = function (event) {
    let file =  event.target.files[0]
    const reader = new FileReader()
    reader.onload = function () {
      console.log(reader.result)
      ...
    }
    reader.readAsDataURL(file)
  }
</script>

canvas 压缩图片

这是图片上传压缩的核心所在,我们先使用CanvasRenderingContext2D.drawImage()方法将上传的图片文件在画布上绘制出来,再使用Canvas.toDataURL()将画布上的图片信息转换成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.toDataURl()

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

  • mimeType(可选): 表示需要转换的图像的mimeType类型。默认值是image/png,还可以是image/jpegimage/webp等。
  • quailty(可选):quality 表示转换的图片质量。范围是 0 到 1。图片的mimeType需要是image/jpeg或者image/webp,其他mimeType值无效。默认压缩质量是 0.92。
var canvas = document.createElement('canvas')
canvas.toDataURL("image/jpeg" 0.8)

到这里,我们先来上 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.toDataURL(mimeType, quality / 100)
      resolve(imageData)
    }
  })
}

将 base64 转化为文件

  • 通过window.atobbase-64字符串解码为binaryString(二进制文本);
  • binaryString构造为multipart/form-data格式;
  • Uint8Arraymultipart格式的二进制文本转换为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,把blobappend 到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 用于上传。

到此这篇关于浅析图片上传及canvas压缩的流程的文章就介绍到这了,更多相关图片上传canvas压缩内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章,希望大家以后多多支持三水点靠木!

HTML / CSS 相关文章推荐
CSS3制作漂亮的照片墙的实现代码
Jun 08 HTML / CSS
如何使用localstorage代替cookie实现跨域共享数据问题
Apr 18 HTML / CSS
详解Html5原生拖拽操作
Jan 12 HTML / CSS
HTML5之SVG 2D入门13—svg对决canvas及长处和适用场景分析
Jan 30 HTML / CSS
五个2015 年最佳HTML5 框架
Nov 11 HTML / CSS
在HTML5中使用MathML数学公式的简单讲解
Feb 19 HTML / CSS
详解移动端html5页面长按实现高亮全选文本内容的兼容解决方案
Dec 03 HTML / CSS
关于h5中的fetch方法解读(小结)
Nov 15 HTML / CSS
canvas绘制太极图的实现示例
Apr 29 HTML / CSS
萌新的HTML5 入门指南
Nov 06 HTML / CSS
html+css实现赛博朋克风格按钮
May 26 HTML / CSS
bootstrapv4轮播图去除两侧阴影及线框的方法
Feb 15 HTML / CSS
原生canvas制作画图小工具的踩坑和爬坑
Jun 09 #HTML / CSS
h5移动端调用支付宝、微信支付的实现
Jun 08 #HTML / CSS
使用SVG实现提示框功能的示例代码
Jun 05 #HTML / CSS
Html5嵌入钉钉的实现示例
Jun 04 #HTML / CSS
浅析数据存储的三种方式 cookie sessionstorage localstorage 的异同
Jun 04 #HTML / CSS
h5页面唤起app如果没安装就跳转下载(iOS和Android)
Jun 03 #HTML / CSS
html5视频自动横过来自适应页面且点击播放功能的实现
Jun 03 #HTML / CSS
You might like
一个简单的自动发送邮件系统(一)
2006/10/09 PHP
php 什么是PEAR?(第二篇)
2009/03/19 PHP
php设计模式 Singleton(单例模式)
2011/06/26 PHP
php递归删除指定文件夹的方法小结
2015/04/20 PHP
PHP中ltrim与rtrim去除左右空格及特殊字符实例
2016/01/07 PHP
PHP无限极分类函数的实现方法详解
2017/04/15 PHP
PHP实现UTF8二进制及明文字符串的转化功能示例
2017/11/20 PHP
javascript flash下fromCharCode和charCodeAt方法使用说明
2008/01/12 Javascript
实现JavaScript中继承的三种方式
2009/10/16 Javascript
IE浏览器打印的页眉页脚设置解决方法
2009/12/08 Javascript
node.js中的fs.chownSync方法使用说明
2014/12/16 Javascript
Javascript递归打印Document层次关系实例分析
2015/05/15 Javascript
原生js与jQuery实现简单的tab切换特效对比
2015/07/30 Javascript
JavaScript实现LI列表数据绑定的方法
2015/08/04 Javascript
关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework)
2016/12/14 Javascript
VUE 实现滚动监听 导航栏置顶的方法
2018/09/11 Javascript
vue2中引用及使用 better-scroll的方法详解
2018/11/15 Javascript
JavaScript实现简单音乐播放器
2020/04/17 Javascript
vue.js基于v-for实现批量渲染 Json数组对象列表数据示例
2019/08/03 Javascript
原生JavaScript实现日历功能代码实例(无引用Jq)
2019/09/23 Javascript
基于jQuery实现可编辑的表格
2019/12/11 jQuery
利用numpy+matplotlib绘图的基本操作教程
2017/05/03 Python
浅谈python 线程池threadpool之实现
2017/11/17 Python
python实现协同过滤推荐算法完整代码示例
2017/12/15 Python
Pytorch 中retain_graph的用法详解
2020/01/07 Python
Python利用PyPDF2库获取PDF文件总页码实例
2020/04/03 Python
Windows下Sqlmap环境安装教程详解
2020/08/04 Python
python实现简单贪吃蛇游戏
2020/09/29 Python
全网最全python库selenium自动化使用详细教程
2021/01/12 Python
西班牙拥有最佳品牌的动物商店:Animalear.com
2018/01/05 全球购物
NFL Game Pass欧洲:在线观看NFL比赛直播和点播,以高清质量播放
2018/08/30 全球购物
给校长的建议书100字
2014/05/16 职场文书
副校长个人对照检查材料思想汇报
2014/10/04 职场文书
新学期红领巾广播稿
2014/10/04 职场文书
中秋节作文(五年级)之关于月亮
2019/09/11 职场文书
html+css合并表格边框的示例代码
2021/03/31 HTML / CSS