这篇工作总结将整理一下如何实现图片压缩。
之所以需要处理图片压缩,是因为现在很多时候从用户那获得图片并上传,其实对图片的质量要求大部分情况下都不高,而各个客户端的硬件能力也比较强,用户能提供比较高质量的图片,但对要求不高的服务端来说却是一种压力,所以在处理上传图片之前,如果能对图片做一步压缩可以减轻用户的流量负担,也可以减轻服务端的压力。
因为从用户那获得的是一个file对象,所以压缩的对象也是file对象。然后压缩可以通过图片的清晰度,尺寸来压缩。最后,因为图片压缩是一个异步处理,需要有一个回调函数来处理,当然,后面可以改成promise的方式。所以实现图片压缩方法,需要传入的参数就是这四个file,option(包含quality和scale)和callback。
1 | const photoCompress = function (file, options, callback){ |
首先,file对象需要转成data:URL格式的Base64字符串,这样图片才能被canvas渲染到画布上。这里用到FileReader对象。它能让Web应用程序异步读取存储在用户计算机上的文件,得到几种格式的文件内容。这里用到FileReader.readAsDataURL()来转格式,然后需要调用FileReader.onload在读取操作完成后执行之后的操作
1 | const photoCompress = function (file, options, callback){ |
获得文件内容之后,就可以来生成一个canvas画布,渲染图片了。先把图片文件加载好,然后在生成canvas标签,宽高直接取图片的宽高,然后生成画布,再把图片渲染到画布上,最后再获得压缩后的图片内容。尺寸的压缩可以在取宽高之后直接使用,得到压缩尺寸后的宽高,而清晰度则在最后获取压缩图片的时候调用canvas.toDataURL()时传入。这一步可以封装一个canvasDataURL()来实现,传入文件内容path,option(包含quality和scale)和callback。
1 | const canvasDataURL = function (path, options, callback){ |
这样就可以通过callback获得压缩后的data URI。但是这样的内容还需要转成file对象,才能用做上传或者其他用。
所以,在调用photoCompress方法时传入的callback中,需要做一步转化。首先要先将data URI中的base64编码截出来,转成blob对象,然后在用blob对象转成file对象。
1 | // 将base64编码转成blob对象 |
为了外部调用使用时是处理同步状态,所以在调用photoCompress方法时会用一个函数包装,利用promise来处理。
1 | compress (file) { |
这样调用的时候,就可以通过then或者async await来拿到压缩后的file文件。