在上一篇文章Javascript 基础夯实 —— 通过代码构建一个包含文件的 FormData 对象中提到了前端压缩图片的功能,所以本篇文章就来实现一下这个功能
前端获取本地图片文件
通过一个类型为的标签,我们可以获取到设备本地的文件,还可以声明一个的属性,这个属性用来过滤可以选择的文件,如果不声明则可以选择所有文件
在这里,的值是,这表示可以选择所有类型的图片文件,包括 png/jpg/jpeg/gif/bmp 等等,如果需要限制可以选择的文件类型,则可以改写成这样:
如果需要多选,还可以再声明一个属性
onchange 事件与获取选择的文件
我们可以通过事件监听到状态的改变,这样就能在选择完文件后,对文件进行操作
元素有一个属性,这个属性的值是一个文件对象数组,用来保存当前选择过的文件
读取文件对象内容
虽然获取到了选择的图片文件,但是我们并不能对 File 对象直接进行压缩的操作,而是需要先读取 File 对象的内容,再对读取到的内容进行操作
读取 File 对象的内容,我们可以通过 FileReader 对象来实现,此处以选择的第一张图片为例:
FileReader 对象上有以下属性及方法:
属性:
readyState:FileReader 当前的状态,有三种值,0-还未开始读取数据;1-正在读取数据;2-数据读取完成
result:在读取完成后才会存在的属性,值是读取到的文件的内容
onload:文件读取完成后触发的事件
error:读取文件时的错误信息
常用方法:
readAsDataURL:将 File 或 Blob 读取为一个 base64 编码的 URL 字符串
readAsText:读取 File 或 Blob 的文本内容,第二个参数可以指定编码类型,默认 utf-8
abort:取消读取的操作
需要注意的是, 和 都是异步的,必须监听 或者在 事件中才能获取到读取到的结果,所以出现多个文件需要遍历读取的情况时,需要特别注意
在上面的代码中,将图片文件读取为了一个 base64 编码的 URL 字符串,下面就可以通过这个字符串来创建一个 Image 对象了:
拿到图片文件生成的 image 对象,下面就可以正式进行图片的压缩了!
前端压缩图片的实现
压缩的实现又要借助到 canvas 画布元素。先来说一下原理,再来实现功能
原理简述
然后再将图片按比例缩放绘制到 canvas 上,再将 canvas 的上下文导出为一个 base64 的 url,导出的过程中我们可以设定导出的压缩比率和导出的图片格式
最终我们拿到了一个压缩后的图片的 base64 编码的 url,我们可以将这个 url 转为 Blob 对象,再通过表单的方式传输到后台。关于这一步,在开头的链接中,也就是上一篇文章已经说过了,在本文中不再赘述:
代码实现
需要注意的几点:
方法是 canvas 上下文环境的方法,而不是 canvas 元素的方法,这个方法可以接收多个参数,并且参数长度不同,作用也不同,在这里的作用是:将 image 从 (0, 0) 的位置开始截取一个宽高为 image.width, image.height 的图像(即将图像完整截取),放置在 canvas 上从 (0, 0) 开始,到 canvas.height, canvas.width 的区域中(也就是完整缩放在 canvas 中)。当传入其他数量参数时,小伙伴们可以参考这个页面:HTML DOM drawImage() 方法
导出图像方法 是 canvas 的方法,第一个参数hi导出的格式,不传或者传入错误格式的话,会默认使用 png 格式;第二个参数是导出的品质系数,范围为 0-1,默认 0.92,但是这个系数只对导出类型为 jpeg 和 webp 的图片生效