通过canvas实现前端方式的图片压缩

51 阅读2分钟

大致思路:

1.将拿到的file文件对象转换成Img元素标签(FileReader)

2.获取该元素标签的宽高,计算需要压缩的尺寸,创建canvas实例,将该元素标签绘制到canvas上

3.通过canvas的tuDataRUL方法返回压缩后图片的base6编码,可根据自己的需求转换成file或者blob

//将DataURL转成file
const dataURLToFile=(dataUrl,fileName)=>{
    const dataArr = dataUrl.split(',')
    const mime = dataArr[0].match(/:(.*);/)[1]
    const originStr = atob(dataArr[1])
    let n = originStr.length
    const u8Arr = new Uint8Array(n)
    while (n--) {
        u8Arr[n] = originStr.charCodeAt(n)
    }
    return new File([u8Arr],fileName, { type: mime })
};

//图片压缩
const compressImg=(file)=>{
    //file文件
    let disposeFile = file;
    //如果当前获取到的file为blob对象,将其转换成file对象
    if(Object.prototype.toString.call(file)==='[object Blob]'){
        disposeFile = new File([file],file.name,{type:file.type});
    }
    //file文件流大小
    const fileSize = parseFloat(parseInt(disposeFile['size'])/1024/1024).toFixed(2);
    //小于1M不压缩
    if(fileSize < 1 )return  file;
    //FileReader 读取单个对象文件
    const reader = new FileReader();
    return new Promise((resolve,reject)=>{
        try{
            //readAsDataURL方法 读取file对象
            reader.readAsDataURL(file);
            //在读取完成时触发
            reader.onload=()=>{
                //创建img元素标签
                const img = new Image();
                console.log(reader.result)
                //将FileReader读取的file对象文件(base64编码)赋值给img的src属性完成file对象文件到Img元素标签的转换
                img.src = reader.result;
                img.onload=()=>{
                    //获取img图片宽高
                    const { width: originWidth, height: originHeight } = img
                    // 设置最大尺寸限制
                    const maxWidth = 1000;
                    const maxHeight = 1000;
                  // 需要压缩的目标尺寸
                    let targetWidth = originWidth, targetHeight = originHeight
                    // 等比例计算超过最大限制时缩放后的图片尺寸
                    if (originWidth > maxWidth || originHeight > maxHeight) {
                        if (originWidth / originHeight > 1) {
                            // 宽图片
                            targetWidth = maxWidth
                            targetHeight = Math.round(maxWidth * (originHeight / originWidth))
                        } else {
                            // 高图片
                            targetHeight = maxHeight
                            targetWidth = Math.round(maxHeight * (originWidth / originHeight))
                        }
                    }
                    //创建canvas对象
                    const canvas = document.createElement("canvas");
                    // canvas对图片进行裁剪,设置图片压缩完的尺寸
                    canvas.width = targetWidth;
                    canvas.height = targetHeight;
                    const ctx = canvas.getContext("2d");
                    // canvas中,png转jpg会变黑底,所以先给canvas铺一张白底
                    ctx.fillStyle = "#fff";
                    // fillRect()方法绘制一个填充了内容的矩形
                    ctx.fillRect(0,0,canvas.width,canvas.height);
                    // 绘制图像
                    ctx.drawImage(img,0,0,targetWidth,targetHeight);
                    // canvas转图片 实现图片压缩
                    let base64;
                    if(fileSize < 1){
                        //图片小于1M 不执行压缩操作
                        base64 = canvas.toDataURL(disposeFile['type'],1)
                    }else if(fileSize > 1 && fileSize < 2){
                        //图片大于1M但是小于2M  图片压缩0.5
                        base64 = canvas.toDataURL(disposeFile['type'],0.5);
                    }else{
                        //图片大于2M 图片压缩0.2
                        base64 = canvas.toDataURL(disposeFile['type'],0.2)
                    }
                    resolve(dataURLToFile(base64,disposeFile.name))
                }
            };
        }catch (e) {
            reject(e);
        }
    })
}
export { compressImg }