0


前端实现图片压缩(干货总结)

前端实现图片压缩方案总结


⚠️⚠️文前推荐一下👉
前端必备工具推荐网站(图床、API和ChatAI、智能AI简历、AI思维导图神器等实用工具):
站点入口:http://luckycola.com.cn/


前文提要

在Web开发中,图片压缩是一个常见且重要的需求。随着高清图片和多媒体内容的普及,如何在保证图片质量的同时减少其文件大小,对于提升网页加载速度、优化用户体验至关重要。前端作为用户与服务器之间的桥梁,实现图片压缩的功能可以显著减轻服务器的负担,加快页面渲染速度。本文将探讨前端实现图片压缩的几种方法和技术。

1. 使用HTML5的

<canvas>

元素

HTML5的

<canvas>

元素为前端图片处理提供了强大的能力。通过JavaScript操作

<canvas>

,我们可以读取图片数据,对其进行处理(如缩放、裁剪、转换格式等),然后输出压缩后的图片。

步骤概述:
  1. 读取图片:使用FileReaderImage对象加载图片。
  2. **绘制到<canvas>**:将图片绘制到<canvas>上,通过调整<canvas>的尺寸或绘图参数来控制压缩效果。
  3. 导出图片:使用canvas.toDataURL()方法将<canvas>内容转换为Base64编码的图片,或使用canvas.toBlob()方法获取Blob对象,以便进一步处理或上传。
示例代码:
functioncompressImage(file, quality, callback){const reader =newFileReader();
    reader.onload=function(e){const img =newImage();
        img.onload=function(){const canvas = document.createElement('canvas');const ctx = canvas.getContext('2d');// 设置canvas的尺寸,这里可以根据需要调整constMAX_WIDTH=800;constMAX_HEIGHT=600;let width = img.width;let height = img.height;if(width > height){if(width >MAX_WIDTH){
                    height *=MAX_WIDTH/ width;
                    width =MAX_WIDTH;}}else{if(height >MAX_HEIGHT){
                    width *=MAX_HEIGHT/ height;
                    height =MAX_HEIGHT;}}

            canvas.width = width;
            canvas.height = height;
            ctx.drawImage(img,0,0, width, height);// 转换为压缩后的图片
            canvas.toBlob(function(blob){callback(blob);},'image/jpeg', quality);};
        img.src = e.target.result;};
    reader.readAsDataURL(file);}// 使用示例const fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change',function(e){const file = e.target.files[0];compressImage(file,0.7,function(blob){// 处理压缩后的图片,如上传或显示
        console.log(blob);});});

2. 利用第三方库(推荐)

除了原生JavaScript和HTML5外,还有许多优秀的第三方库可以帮助我们更方便地实现图片压缩,如

image-magic-adapter、compressorjs

pica

等。这些库通常提供了更丰富的配置选项和更好的兼容性支持。

特别推荐的库: image-magic-adapter
这个三方库是国内开发者提供的,他集成许多图片处理能力,包括“图片压缩”、“图片格式转换”、“图片加水印”等等,非常方便,而且这个库还有官网也可以直接使用这些功能.

库官网:https://www.npmjs.com/package/image-magic-adapter

在线图片处理工具官网:https://luckycola.com.cn/public/dist/imageTool.html

使用 image-magic-adapter示例:
// 引入image-magic-adapterimport ImageMagicAdapter from'image-magic-adapter';let ImageCompressorCls = ImageMagicAdapter.ImageCompressorCls;const imageCompressor =newImageCompressorCls();// 默认压缩质量// -----------------------------------------图片压缩-----------------------------------------
        document.getElementById('quality').addEventListener('input',()=>{const quality =parseFloat(document.getElementById('quality').value);
            imageCompressor.quality =1- quality;// 更新压缩质量
            console.log('更新后的压缩质量:', imageCompressor.quality);});
        document.getElementById('compress').addEventListener('click',async()=>{const fileInput = document.getElementById('upload');if(!fileInput.files.length){alert('请上传图片');return;}const files = Array.from(fileInput.files);const progress = document.getElementById('progress');const outputContainer = document.getElementById('outputContainer');const downloadButton = document.getElementById('download');const progressText = document.getElementById('progressText');

            outputContainer.innerHTML ='';
            downloadButton.style.display ='none';
            progress.style.display ='block';
            progress.value =0;
            progressText.innerText ='';// compressImages参数说明://  第一个参数: files:需要压缩的文件数组//  第二个参数: callback:压缩完成后的回调函数//  第三个参数: 若是压缩png/bmp格式,输出是否保留png/bmp格式,默认为true(建议设置为false)// 注意:如果 第三个参数设置true压缩png/bmp格式后的输出的文件为原格式(png/bmp)且压缩效果不佳,就需要依赖设置scaleFactor来调整压缩比例(0-1);如果设置为false,输出为image/jpeg格式且压缩效果更好。// 设置caleFactor为0-1,值越大,压缩比例越小,值越小,压缩比例越大(本质是改变图片的尺寸),例: imageCompressor.scaleFactor = 0.5;await imageCompressor.compressImages(files,(completed, total)=>{const outputImg = document.createElement('img');
                outputImg.src = imageCompressor.compressedImages[completed -1];
                outputContainer.appendChild(outputImg);
                progress.value =(completed / total)*100;
                progressText.innerText =`已完成文件数: ${completed} / 总文件数: ${total}`;if(completed === total){
                    downloadButton.style.display ='inline-block';}},false);

            downloadButton.onclick=()=>{if(imageCompressor.compressedImages.length >0){
                    imageCompressor.downloadZip(imageCompressor.compressedImages);}};});
<h4>图片压缩Demo</h4><inputtype="file"id="upload"accept="image/*"multiple/><br><labelfor="quality">压缩比率:(比率越大压缩越大,图片质量越低)</label><inputtype="range"id="quality"min="0"max="0.9"step="0.1"requiredvalue="0.5"/><br><buttonid="compress">压缩图片</button><br><progressid="progress"value="0"max="100"style="display: none;"></progress><br/><spanid="progressText"></span><br><divid="outputContainer"></div><br><buttonid="download"style="display: none;">下载已压缩图片</button>

3. gif图片压缩(拓展)

GIF(Graphics Interchange Format)图片是一种广泛使用的图像文件格式,特别适合用于显示索引颜色图像(如简单的图形、图标和某些类型的图片),同时也支持动画。尽管GIF图片本身可以具有压缩特性,但在前端和后端进行压缩处理时,存在几个关键考虑因素,这些因素可能导致在前端直接压缩GIF不如在后端处理更为有效或合理。

下面提供一个厚后端通过node实现gif压缩的方案:
1、下载imagemin、imagemin-gifsicle和image-size库
2、注意依赖的库的版本,不然可能会报错

"image-size":"^1.1.1","imagemin":"7.0.1","imagemin-gifsicle":"^7.0.0",
node压缩gif实现如下:
const imagemin =require('imagemin');const imageminGifsicle =require('imagemin-gifsicle');const sizeOf =require('image-size');// 压缩 GIF colors[0-256]constcompressGifImgFn=async(inputBase64, colors =200,successFn=()=>{},failFn=()=>{})=>{try{if(inputBase64.length <=10){
            failFn &&failFn('inputBase64 无效')return;}// 获取输入 GIF 的尺寸const originalSize =getBase64Size(inputBase64);
        console.log('Original Size:', originalSize);// 转换 Base64 为 Bufferconst inputBuffer =base64ToBuffer(inputBase64);const outputBuffer =await imagemin.buffer(inputBuffer,{plugins:[imageminGifsicle({// interlaced的作用 是,是否对 GIF 进行隔行扫描interlaced:true,// optimizationLevel的作用是,设置压缩的质量,0-3optimizationLevel:3,// // progressive的作用是,是否对 GIF 进行渐进式压缩// progressive: true,// // palette的作用是,是否对 GIF 进行调色板优化// palette: true,// // colorspace的作用是,是否对 GIF 进行色彩空间转换// colorspace: true,
                    colors
                })]});// 转换压缩后的 Buffer 为 Base64const outputBase64 =bufferToBase64(outputBuffer);// 获取压缩后 GIF 的尺寸const compressedSize =getBase64Size(outputBase64);
        console.log('Compressed Size:', compressedSize);// 输出压缩后的 Base64 GIF// console.log(outputBase64);let gifCompressRes ={
            outputBase64,
            compressedSize,
            originalSize
        }
        successFn &&successFn(gifCompressRes);}catch(error){
        console.error('Error compressing GIF:', error);
        failFn &&failFn(error)}};// 将 Base64 字符串转换为 Bufferfunctionbase64ToBuffer(base64){const base64Data = base64.split(',')[1];// 如果是 data URL, 删除前缀return Buffer.from(base64Data,'base64');}// 将 Buffer 转换为 Base64 字符串functionbufferToBase64(buffer){return`data:image/gif;base64,${buffer.toString('base64')}`;}//获取base64图片大小,返回kb数字functiongetBase64Size(base64url){try{//把头部去掉let str = base64url.replace('data:image/png;base64,','');// 找到等号,把等号也去掉let equalIndex = str.indexOf('=');if(str.indexOf('=')>0){
        str = str.substring(0, equalIndex);}// 原来的字符流大小,单位为字节let strLength = str.length;// 计算后得到的文件流大小,单位为字节let fileLength =parseInt(strLength -(strLength /8)*2);// 由字节转换为kblet size ="";
        size =(fileLength /1024).toFixed(2);let sizeStr = size +"";//转成字符串let index = sizeStr.indexOf(".");//获取小数点处的索引let dou = sizeStr.substr(index +1,2)//获取小数点后两位的值if(dou =="00"){//判断后两位是否为00,如果是则删除00                return sizeStr.substring(0, index)+ sizeStr.substr(index +3,2)}return size;}catch(error){
        console.log('getBase64Size error:', error);return0;}};

注意事项

  • 压缩质量与文件大小:压缩质量越高,图片质量越好,但文件大小也越大;反之亦然。需要根据实际需求调整。
  • 兼容性:虽然现代浏览器普遍支持<canvas>和Blob等特性,但在一些老旧浏览器上可能存在问题,需要做好兼容性处理。
  • 性能考虑:对于大图片或高频率的图片处理,前端压缩可能会占用较多CPU资源,影响页面性能。

本文转载自: https://blog.csdn.net/qq_48896417/article/details/141830105
版权归原作者 LuckyCola2023 所有, 如有侵权,请联系我们删除。

“前端实现图片压缩(干货总结)”的评论:

还没有评论