首页 前端知识 html5 canvas技术前端进行图片压缩

html5 canvas技术前端进行图片压缩

2023-05-14 16:05:34 前端知识 前端哥 600 586 我要收藏

canvas应用的图片压缩算法实现 前端图片压缩应用场景前端页面限制用户只可以上传5MB大小的图片 前端在接受到用户上传的图片之后,服务器只允许上传1MB大小的图片,此时需要前端将图片先进行压缩,压缩之后再调用图片上传接口将图片上传第一步:创建input元素:

前端图片压缩应用场景

  1. 前端页面限制用户只可以上传5MB大小的图片
  2. 前端在接受到用户上传的图片之后,服务器只允许上传1MB大小的图片,此时需要前端将图片先进行压缩,压缩之后再调用图片上传接口将图片上传

第一步:创建input元素,监听input表单域的change事件

  1. 创建一个input元素,并且设置HTML5新增的type为file
  2. 监听input元素的change事件,并通过e.target.files拿到用户上传的文件列表数组
  3. 获取用户上传的文件对象,校验其是否为空
  4. 校验文件的type类型是否为图片类型
  5. 校验文件的size大小是否超出5MB
  6. 如果校验通过,那么才开始进行图片压缩
<input type="file" id="upload"></input><script type="text/javascript">    const upload = document.getElementById('#upload');    const acceptType = ['image/png','image/jpeg','image/jpg'];    const maxSize = 3 * 1024 *1024;         upload.addEventListener('change',function(e){        let file = e.target.files[0];        if(!file)return;        let {type:fileType,size:fileSize} = file;        if(!acceptType.includes(fileType)){            alert(`不支持${fileType}类型文件`);            upload.value = '';            return;        }        if(fileSize > maxSize){            alert(`文件大小超出3MB!`);            upload.value = '';            return;        }        convertImageToBase64(file,function(base64Image){            compress(base64Image,uploadToServer);        });    }) </script>

第二步:图片压缩第一步先将用户上传图片转化为base64格式字符串

  1. 创建一个浏览器内置的FileReader对象的实例reader
  2. 调用reader.readAsDataURL()方法,参数接收一个blob对象或者file对象
  3. 调用该方法之后会开始读取传入的文件file,读取完成后会触发load完成事件
  4. 在load事件中,通过e.target.result或者reader.result获取file对应的base64格式字符串
  5. 执行传入的callback函数,此时开始执行compress压缩函数
  6. 将reader指向null,防止内存泄漏
function convertImageToBase64(file,callback){    const reader = new FileReader();    reader.addEventListener('load',function(e){        let base64Image = e.target.result;        callback && callback(base64Image);        reader = null;    })    reader.readAsDataURL(file);}

第三步:执行compress方法,开始压缩图片

  1. 创建一个image对象,为了方便获取用户上传图片的原始宽高
  2. 设置最大宽度和高度
  3. 将image的src属性设置为base64Image,并监听image的load事件
  4. 当load事件触发后,在事件回调函数中进行如下逻辑:
  5. 设置压缩比ratio
  6. 设置是否需要压缩的变量needCompress
  7. 校验原始宽度超出宽度,计算压缩比,如果超出,此时最大高度需要等比例变化
  8. 校验原始高度超出高度,计算压缩比,如果超出,此时最大宽度需要等比例变化
  9. 如果原始宽高都没有超出,那么需要将最大宽高的值修改为原始宽高
  10. 动态创建一个canvas元素
  11. 设置canvas元素的宽高属性分别为最大宽度和高度后插入到页面中
  12. 设置canvas的visibility属性为hidden或者visibile,看具体项目需求
  13. 获取ctx 2d上下文对象
  14. 清空上一次绘图的画布ctx.clearRect(0,0,最大宽度,最大高度)
  15. 绘制图片ctx.drawImage(image,0,0,最大宽度,最大高度)绘制出图片,此时已经将图片的尺寸进行了压缩
  16. 输出图片canvas.toDataURL('image/jpeg',0.8);前者是输出格式,后者是输出质量。选jpeg本来就会对图片进行压缩,输出质量也会进行压缩。
  17. 拿到上一步输出的base64格式的图片地址,将其作为参数传递给callback,compress函数中的callb18. 通过对比image.src.length可以计算压缩前后的压缩比
function compress(base64Image,callback){    const image = new Image();    let maxW = 1024,        maxH = 1024;     image.addEventListener('load',function(e){        const needCompress = false,              ratio = null;        if(image.naturalWidth > maxW){           needCompress = true;           ratio = naturalWidth / maxW;           maxH = naturalHeight/ratio;        }        if(image.naturalHeight > maxH){            needCompress = true;            ratio = naturalHeight / maxH;            maxW = naturalWidth/ratio;        }        if(!needCompress){             maxW = naturalWidth;             maxH = naturalHeight;        }                 let canvas = document.createElement('canvas');        canvas.width = maxW;        canvas.height = maxH;        document.body.appendChild(canvas);        canvas.style.visibility = 'hidden';        let ctx = canvas.getContext('2d');        ctx.clearRect(0,0,maxW,maxH);        ctx.drawImage(image,0,0,maxW,maxH);image是要生成的image对象        let compressedBase64Image = canvas.toDataURL('image/jpeg',0.8);        canvas.remove();                 callback && callback(compressedBase64Image);        const _ratio = base64Image.length / compressedBase64Image.length;        console.log('图片压缩比为:',_ratio);             })         image.src = base64Image;}

第四步:将图片上传至服务器

  1. 接收传递的压缩后图片的base64字符串compressImage
  2. 将其上传至服务器
function uploadToServer(compressedBase64Image){    console.log('上传的图片为:'   compressedBase64Image);    axios.post({        url:'192.168.01.02/api/upload',        data:{                     },        headers:{            'Content-Type':'multipart/form-data'        }    })}

最终干货(代码)如下:

<input type="file"  id="upload"/>
function convertImageToBase64(file,callback){    // 实例化FileReader对象,主要用于读取文件内容    let reader = new FileReader();    // 监听文件加载完成的事件    reader.addEventListener('load',function(e){        // 直接用reader实例的result属性拿到base64格式        // console.log(reader.result);                 // e.target.result获取到文件的base64格式        // console.dir(e.target.result);        let base64Image = e.target.result;        // 执行callback()        callback && callback(base64Image);        // 将reader指向null防止内存泄漏        reader = null;    })    // 调用实例的readAsDataURL方法    reader.readAsDataURL(file);} function uploadToServer(compressedBase64Image){    console.log('上传的图片为:'   compressedBase64Image);    axios.post({        url:'192.168.01.02/api/upload',        data:{                     },        headers:{            'Content-Type':'multipart/form-data'        }    })} function compress(base64Image,callback){    const image = new Image();    let maxWidth = 1024;    let maxHeight = 1024;         image.addEventListener('load',function(e){        let ratio;        let needCompress = false;        if(image.naturalWidth > maxWidth){            needCompress = true;            ratio = image.naturalWidth / maxWidth;            maxHeight = image.naturalHeight / ratio;        }        if(image.naturalHeight > maxHeight){            needCompress = true;            ratio = image.naturalHeight / maxHeight;            maxWidth = image.naturalWidth / ratio;        }        // 如果不需要压缩 那么需要获取图片的实际尺寸        if(!needCompress){            maxWidth = image.naturalWidth;            maxHeight = image.naturalHeight;        }                 // 创建一个画步  画布大小 就是压缩尺寸后的图片大小        const canvas = document.createElement('canvas');        canvas.width = maxWidth;        canvas.height = maxHeight;                 let ctx = canvas.getContext('2d');        ctx.clearRect(0,0,maxWidth,maxHeight);        ctx.drawImage(image,0,0,maxWidth,maxHeight);        const compressImage = canvas.toDataURL('image/jpeg',0.8);        canvas.remove();                 // 此时已经拿到压缩后图片的base64格式 下面要将图片上传到服务器        callback && callback(compressImage);                          const _image = new Image();        _image.src = compressImage;        _image.id = 'chooseImage';        document.body.appendChild(_image);                          console.log(base64Image.length/compressImage.length);压缩比    })    image.src = base64Image;} const upload = document.getElementById('#upload');const acceptType = ['image/png','image/jpeg','image/jpg'];const maxSize = 3 * 1024 *1024; upload.addEventListener('change',function(e){    let file = e.target.files[0];    if(!file)return;    let {type:fileType,size:fileSize} = file;    if(!acceptType.includes(fileType)){        alert(`不支持${fileType}类型文件`);        upload.value = '';        return;    }    if(fileSize > maxSize){        alert(`文件大小超出3MB!`);        upload.value = '';        return;    }    convertImageToBase64(file,function(base64Image){        compress(base64Image,uploadToServer);    });})


转载请注明出处或者链接地址:https://www.qianduange.cn//article/61.html
评论
发布的文章

jQuery AJAX请求的统一封装

2024-02-01 12:02:53

jQuery知识学习

2024-02-01 12:02:53

JQuery——动画效果

2024-02-01 12:02:52

jQuery复习

2024-02-01 12:02:51

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!