前言🏄🏄
在学习的时候,有时候看到一些一些网站的图片是经过压缩处理的,因为压缩之后的图片会节省一部分你的内存空间,这样的话也可以提升性能,于是就比较好奇这是如何实现的,今天我们就简单的实现一下
压缩图片的原理👨🚀👨🚀
其实我们实现压缩的本质原理是通过使用canvas中的toDataURL
来进行图片的压缩操作,但是中间需要经过一系列的加工处理,下面我将详细的讲解细节的操作:
const init=()=>{ const selectPicture = document.querySelector("#selectImg"); const originalPreview = document.querySelector("#imgPreview"); const compressPreview = document.querySelector("#compressImg"); // 绑定点击事件 function BindEvent() { selectPicture.addEventListener("change", (e) => { const imgFiles = e.target.files[0]; console.log(e.target.files[0]); fn(imgFiles); }); } BindEvent(); .....剩余内容在下面 } init()
- 首先我们创建一个init函数,我们的代码都写在这个函数中,并且我们还在里面写了一个BindEvent函数,将所有的点击事件都写在这个函数中,这样做的目的是使代码更加的模块化
- 首先我们要获取DOM对象,其中我们还要给selectPicture绑定一个change事件,这个元素其实是input type类型为file,当我们触发事件的时候会让我们选择一个图片资源我们可以通过e.target.files[0]来获取这个图片的属性包含这个图片的名称(name),类型(type)等
- 紧接着我们要将获取到的图片的属性传递给fn这个函数,这个函数要对图片进行一些后续的处理
FileReader对象 🍊🍊
首先我们先了解一下FileReader这个对象
简单的来讲就是FileReader这个对象允许应用程序异步的读取计算机的文件内容,其中这个对象提供了一些方法,我们等会会用到它提供的一些方法。
readAsDataURL(file)
:读取文件内容,结果用data:url的字符串形式表示readAsText(file,encoding)
:按字符读取文件内容,结果用字符串形式表示readAsArrayBuffer(file)
:按字节读取文件内容,结果用ArrayBuffer对象表示
// 读取图片原始的base64 const fn = (imgFiles) => { const render = new FileReader(); render.readAsDataURL(imgFiles); render.onload = () => { // console.log(render.result); // 将图片压缩处理 originalPreview.setAttribute("src", render.result); imageCompression(render.result, 40, "image/jpg"); }; // 将图片转化为base64形式 };
在这个函数中我们通过调用readAsDataURL
这个方法,这个方法可以用来读取指定的文件,在读取完成之后在render上面的 result
属性将包含一个data:
URL格式的字符串 (base64编码) 以表示所读取文件的内容。
我们在使用 readAsDataURL
方法的一般流程如下:
- 获取文件对象(例如,通过文件选择框选择文件)
- 创建一个
FileReader
对象 (即为new FileReader())。 - 为
FileReader
对象绑定onload
事件处理程序,以在文件读取完成时执行相应的操作。 - 调用
readAsDataURL
方法,将文件作为参数传递给它。 - 在
onload
事件处理程序中,通过result
属性获取读取到的数据 URL。(这个数据的格式是base64)
我们在这个函数中将原始图片通过setAttribute方法给src属性设置值render.result(base64)
在这里我们接下来就需要调用压缩图片的函数
首先这个函数接收三个值分别是:
imageURL
:图片的路径,这里是指处理过的路径(我们这里是base64格式)quality
:转换之后的图片质量,这里这里取值是(0-100)imageType
:这个表示图片的格式(这里的图片格式就是在Files中的图片格式 ,也就是通过e.target.files[0]中的图片格式)
图片压缩函数⛹️♀️⛹️♀️
// 压缩函数 const imageCompression = (imageURL, quality, imageType) => { let canvas = document.createElement("canvas"); let img = document.createElement("img"); img.src = imageURL; img.onload = () => { // 在实际的工作中,根据业务来计算相应的宽度,这里只是进行一个演示的小demo canvas.width = 300; canvas.height = 300; // 获取上下文 let ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0, 300, 300); // 将图片压缩 let compressImage = canvas.toDataURL(imageType, quality / 100); console.log(compressImage); compressPreview.setAttribute("src", compressImage); }; };
- 首先在这个函数中我们要创建
canvas
元素和一个img
元素 - 我们要给创建的img元素的src赋值为imgURL,紧接着我们需要给img注册
onload
方法,确保在img加载完成之后执行压缩操作 - 在加载事件中通过
canvas
创建上下文,这里我们创建一个2d的上下文(创建一个CanvasRenderingContext2D
对象作为2D渲染的上下文) - 我们还需要给canvas设置宽高,当然这里我们只是做一个示例,因此我们的宽高都定义为300,在实际的开发中要以真实的业务需求为主。
- 前期工作做完之后我们就通过调用创建的上下文
ctx
来调用drawImage将图片画在canvas(画布)上,绘制的起始点是(0, 0)
,绘制后的宽度和高度都被设置为300
像素。这意味着最终压缩得到的图像大小将是300x300
像素。 - 然后我们就要实现最终的压缩操作了,通过调用canvas上的toDataURL方法来实现压缩操作,这个方法接受两个参数
imageType
表示输出的数据 URL 的图像类型(如"image/jpeg"
、"image/png"
等),quality
表示图像的质量,取值范围为0
到1
,所以我们要对传递进来的quality/100 - 最后将压缩的图片通过setAttribute设置到src上面。
压缩前后的图片进行对比:🚴♀🚴♀
大小的改变:
不难看出,在压缩之后的图片大小上缩小了3倍。这节省了空间,在一些显示图片很多的网站就可以使用这种压缩,在页面展示的时候可以显示这种压缩之后的图片,当点击进去之后可以显示原本没有压缩的图片,这样就节省了很多的性能。
但是压缩之后的图片确实没有之前美观,所以这是有舍有得,我们可以在具体的情景中灵活的使用。
总结🔑🔑
这次通过对图片压缩的学习,是自己有了解学习了之前所不知道的知识,比如图片的存储形式以及FileReader之类的,使自己收获很多。