前端奇淫技术:图片压缩、方向纠正、预览、上传插件

原创 智云编程 随笔 前端 159阅读 7 天前 举报

前言

相信大家在做项目过程中,经常会遇到上传图片到后端,但是由于图片过大,需要对图片压缩处理。特别在移动端,手机拍的照片普遍过于大了,我们有时候只是需要上传一张头像,很小就够用了。还有在部分手机上(已知苹果手机)拍的照片存在方向角度问题,这时就需要我们来纠正图片角度了。

很多同学多数时候是在用别人写好的图片压缩上传插件。针对我们的需求,这些插件有时候不能达到我们最理想的效果,自己写呢,又不会写,很是头疼。今天就深入剖析讲解下,教会大家编写自己的图片压缩、方向纠正插件,以及预览和上传压缩后图片数据。

文中用到的一些H5的api和EXIF.js等知识点如果不懂的话,请先阅读文末尾的结语中的知识点资料。

实现原理

压缩图片并且上传主要用到filereader、canvas 以及 formdata 这三个h5的api和插件EXIF.js。逻辑并不难。整个过程就是:

  (1)用户使用input file上传图片的时候,用filereader读取用户上传的图片数据(base64格式)
  (2)把图片数据传入img对象,然后将img绘制到canvas上,用EXIF.js对图片方向进行纠正,再调用canvas.toDataURL对图片进行压缩,获取到压缩后的base64格式图片数据,转成二进制
  (3)获取到压缩后的图片二进制数据,预览。
  (4)将压缩后的图片二进制数据塞入formdata,再通过XmlHttpRequest提交formdata

  如此四步,就完成了图片的压缩、方向纠正、预览和上传。

插件设计思考

考虑到在实际项目中,可能用不同的开发框架(vue.js/JQ/react.js/angular.js/anu.js等),图片预览的UI样式也可能不同,图片数据上传方法可能不同。因为图片压缩和方向纠正这两块的逻辑多变性比较低,我们这里把图片压缩和方向纠正抽离出来,封装为一个插件库。

【一】获取图片数据

先是获取图片数据,也就是监听input file的change事件,然后获取到用来压缩上传的文件对象files,将files传到【图片压缩、方向纠正插件】中进行处理。

这时候根据每个人的需求,也可以预览未压缩的图片。

【二】图片压缩、方向纠正插件实现

上面做完图片数据的获取后,就可以做process压缩图片的方法了。而压缩图片也并不是直接把图片绘制到canvas再调用一下toDataURL就行的。

  在IOS中,canvas绘制图片是有两个限制的:

  首先是图片的大小,如果图片的大小超过两百万像素,图片也是无法绘制到canvas上的,调用drawImage的时候不会报错,但是你用toDataURL获取图片数据的时候获取到的是空的图片数据。

  再者就是canvas的大小有限制,如果canvas的大小大于大概五百万像素(即宽高乘积)的时候,不仅图片画不出来,其他什么东西也都是画不出来的。

  应对上面两种限制,我把图片宽度、高度压缩控制在1000px以内,这样图片最大就不超过两百万像素了。在前端开发中,1000px*1000px基本可以满足绝大部分的需求了。当然了还有更完美的瓦片式绘制的方法,我们这里就说瓦片式绘制方法了。

  如此一来就解决了IOS上的两种限制了。

  除了上面所述的限制,还有两个坑,一个就是canvas的toDataURL是只能压缩jpg的(这句话的详细解释可以看下面的Tip讲解),当用户上传的图片是png的话,就需要转成jpg,也就是统一用canvas.toDataURL('image/jpeg', 0.5) , 类型统一设成jpeg,而压缩比就自己控制了。

  另一个就是如果是png转jpg,绘制到canvas上的时候,canvas存在透明区域的话,当转成jpg的时候透明区域会变成黑色,因为canvas的透明像素默认为rgba(0,0,0,0),所以转成jpg就变成rgba(0,0,0,1)了,也就是透明背景会变成了黑色。解决办法就是绘制之前在canvas上铺一层白色的底色。

在压缩图片之前,我们判断图片角度,如果图片角度不正确,还需要用EXIF.js把图片角度纠正过来。

压缩完图片,把base64的图片数据转成二进制数据存储到暂存区中,等待被getBlobList获取使用。

Tip: canvas的toDataURL是只能压缩jpg这句话我可能说的不清楚,我想表达的意思是这个api无论是jpeg还是png,最后导出的时候,都跟jpeg没啥差别了。因为png图片的透明性质在canvas中是无效的,会被canvas添加默认的黑色背景,我在文中讲解的时候,用白色背景处理了,所以最后导出的图片,无论你设置的是png还是jpeg都跟jpeg没啥区别了,因为无法保持png的透明度性质了

Exif.js 提供了 JavaScript 读取图像的原始数据的功能扩展,例如:拍照方向、相机设备型号、拍摄时间、ISO 感光度、GPS 地理位置等数据。
Exif.js官方github 仓库地址:github.com/exif-js/exi…

【三】获取压缩后的图片二进制数据,预览图片

完成图片压缩后,就可以获取压缩后的图片二进制数据了,把获取到的图片二进制数据存起来;获取到数据后,可以拿来预览。

由于实际项目中,每个项目的UI样式设计可能不一样,开发者可以根据自己的UI样式来预览图片。

【四】提交图片数据到后台

new一个formdata对象,将上一步获取到的 blobFileList 图片二进制数据 append 到 formdata中,用任意你喜欢的ajax库进行上传。当然也可以用原生ajax上传。

文中用到了一些H5的知识点,不懂的童鞋可以进入下面的知识点资料地址,详细阅读
HTMLCanvasElement.toDataURL()
CanvasRenderingContext2D.drawImage()
FileReader()
FormData
Blob()
EXIF.js中文博客文章

自己是从事了五年的前端工程师

如果你依然在编程的世界里迷茫,不知道自己的未来规划,可以加入web前端学习交流圈:784783012 里面可以与大神一起交流并走出迷茫。新手可免费领取学习资料,看看前辈们是如何在编程的世界里傲然前行不停更新最新的教程和学习方法(详细的前端项目实战教学视频),有想学习web前端的,或是转行,或是大学生,还有工作中想提升自己能力的,正在学习的小伙伴欢迎加入

点击:加入

评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复