实现图片的压缩,上传功能

实现图片的压缩,上传功能

简言:在前端开发中,我们经常会遇见图片上传等功能,
很多前端工作者 都知道利用input的 file功能实现图片上传的样式
实现图片的压缩,上传功能_第1张图片
常用的可能是 用一个a标签包裹着input 实现按钮状的上传样式
实现图片的压缩,上传功能_第2张图片
但是在深层次的上传和压缩功能 却知知甚少

下边我将以个人案例帮助大家了解 上传 压缩等功能

首先 图片压缩的原理是 获取当前图片文件转化成base64格式, 创建image对象把图片的base64赋值上去
获取改图片的实际大小,定义需要压缩后呈现的尺寸 除以当前的图片尺寸 得出 压缩比.
利用压缩比计算出 实际压缩后的图片
(有人会问 我可以直接定义图片的大小啊 比如800*800 还计算干嘛)
答:会变形 失贞 我们希望压缩后的图片比例和之前一样.
最后把计算后的尺寸 利用canvas 绘制出来 并使用canvas.toDataURL 导出 完成压缩
最后再计算出 压缩后的base64地址 生成一个回调完成上传;

不多BB 上代码

按钮样式:给新手看的 大佬跳过

 .import_btn {
     
            display: block;
            margin: 100px;
            width: 50px;
            text-align: center;
            color: #fff;
            border-radius: 5px;
            position: relative;
            text-decoration: none;
            padding: 10px 20px;
            background: #e56233;

        }

        #upload {
     
            position: absolute;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            opacity: 0;
        }
 <a href="javascript:;" class="import_btn"> 上传
        <input type="file" id="upload">
    a>

上逻辑:

   		const ACCEPT = ["image/png", "image/jpg","image/jpeg"]
        const MAXSIZE = 1920 * 1080;
        const MAXSIZE_STR = '1MB';
        function convertImageToBase64(file, callback) {
     
            // 实例化reader对象

            
            let reader = new FileReader(); //FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件
            reader.addEventListener("load", function (e) {
     
                const base64Image = e.target.result;
                callback && callback(base64Image); //执行回调 把得到base64传递出去
                
                // 使用完成重置reader 释放内存
                reader = null;
            });

            reader.readAsDataURL(file);
        };

        function compress(base64Image,callback) {
     
            // 创建一个image 对象
            const image = new Image();
            // 设置最大宽高
            let maxW = 1024;
            let maxH = 1024;

            // load  指图片加载完成 自动执行
            image.addEventListener('load', function (e) {
     
                let ratio; //图片的压缩比
                let needCompress = false;//是否需要进行压缩
               

                if (maxW < image.naturalWidth) {
        //naturalWidth  图片的实际宽度
                    needCompress = true;         //需要压缩

                    ratio = image.naturalWidth / maxW;//获得压缩比
                    maxH = image.naturalHeight / ratio   //高度根据获取的压缩比 同比进行压缩
                };

                // 进行宽高俩次判断 防止宽度符合后直接跳过
                if (maxH < image.naturalHeight) {
     
                    needCompress = true;
                    ratio = image.naturalHeight / maxH;
                    maxW = image.naturalWidth / ratio;
                };

                // 如果图片过小 就取实际尺寸
                if (!needCompress) {
     
                    maxW = image.naturalWidth;
                    maxh = image.naturalHeight;
                }

                // 把压缩后的图片绘制出来
                const canvas = document.createElement("canvas"); //创建Dom
                canvas.setAttribute("id", "_compress_");//添加一个id
                canvas.width = maxW;
                canvas.height = maxH;
                canvas.style.visibility = "hidden";//压缩过程 bu可见
                document.body.appendChild(canvas);
                
                // 绘制
                const ctx=canvas.getContext("2d");//创建2d绘制
                ctx.clearRect(0,0,maxW,maxH);//清理画布上原有的像素 防止图片叠加 坐标
                ctx.drawImage(image,0,0,maxW,maxH);//绘制图片 起始坐标 图片大小

                // 获取压缩后图片的 base64
                const compressImage=canvas.toDataURL("image/jpeg",0.9);
                callback&&callback(compressImage);//执行回调函数  传出压缩后的照片

                //展示图片(压缩后) 后期可剔除
                const _image=new Image();
                _image.src=compressImage;
                document.body.appendChild(_image);
                canvas.remove();
            });

            //展示   把传递过来的base64(未压缩)路径赋值到新创建的image上
            image.src = base64Image;
            document.body.appendChild(image);
        };

        // 回调函数 把压缩后的base64传给后端 实现上传
        function uploadToServer(compressImage){
     
            // console.log("aka",compressImage);
        }


        // 给 input绑定监听事件 获取到上传的图片信息
        const upload = document.getElementById('upload');
        upload.addEventListener("change", function (e) {
     
            // console.log(e.target.files); 当前文件的信息

            // 结构赋值
            const [file] = e.target.files;
            const {
      type: fileType, size: fileSize } = file;
            
            /*
            *  非空判断
            */
            if (!file) {
     
                return
            }

            /*
            * 
                ES6写法 ACCEPT [上边定义的图片类型]  includes:判断有无 .前的数据类型
            */
            if (!ACCEPT.includes(fileType)) {
     
                alert('不支持[' + fileType + ']文件类型');
                upload.value = '';
                return;
            }

            /*
            *  尺寸判断
            */
            if (fileSize > MAXSIZE) {
     
                alert(`文件超出${
       MAXSIZE_STR}!`);
                upload.value = '';
                return;
            }

            /*
            *   压缩图片
                1.图片转为base64
                回调+回调+回调
            */
            convertImageToBase64(file,(base64Image)=> compress(base64Image,uploadToServer));

        })

如果你仍然觉得 看起来有些困难:我在最后 补一段注释:

前言  图片压缩上传是一个相对复杂的功能
            *       1.需要一个上传按钮  input的file 格式
                    2.监听input框的 change事件 上传成功后 通过files 拿到图片的各种信息
                    3.通过对文件的前置判断,类型 可上传大小 宽高等..
                    4.图片压缩:.首先将获取到的图片转化成base64格式
                           通过FileReader对象(webAPI 可获取储存在计算机上的文件) 
                           调用他的API readAsDataURL(file)

                           readAsDataURL() 方法会读取指定的 Blob 或 File 对象。
                           读取操作完成的时候,readyState 会变成已完成DONE,
                           并触发 loadend 事件,同时result 属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容。

                           获取成功后,执行 compress() 回调事件 属于压缩核心;.compress属于压缩的核心代码
                            创建一个图片的Dom  new Image 
                            把我们获取到的base64地址 赋值给这个图片 然后加载到页面上
                            在 监听image .load (图片加载完成的回调);
                            此时已获取到 当前base64图片的实际大小 尺寸
                            然后我们对 需要展示的图片占比和实际的图片占比
                            当图片超出我们需要压缩后的尺寸时  得出压缩比例 radio(实际尺寸/需要压缩的尺寸);
                            利用压缩比计算出 图片压缩后的尺寸 并使得图片不会变形
                        
                        三.创建一个canvas 把计算后的尺寸赋值给canvas   并设置该canvas不可见(理解为 压缩过程隐藏) 
                            拿到canvas对象,调用canvas.drawImage绘制出来;并转换成需要呈现的图片格式
                            const compressImage=canvas.toDataURL("image/jpeg",0.9); (格式,图片质量);
                            此时已经拿到压缩后的 图片base64
                            通过callback传递给后端 即可完成上传

                         四.为了更好的演示 我在案例中分别展示了2张图片(压缩前 压缩后);实际开发中,可将这部分逻辑删除               

你get 了啵 T_T

你可能感兴趣的:(前端,Javascript,javascript,js)