前端使用canvas,处理图片压缩上传服务器

前端总是遇到一些上传图片的需求,当用户上传的图片过大时,为减轻服务器压力,就需要对图片进行一定的压缩,然后上传到我们的服务器

简单说下实现思路,完整代码在下面,注释比较详细
一、将input标签设置为type="file"便可实现选择本地图片的功能,accept属性表示接收图片的类型,我们监听input的change事件,并将用户上传的图片进行处理

二、将用户上传的文件信息转换成base64格式的数据

三、创建一个canvas对象,根据自身需求对用户上传的图片进行尺寸的压缩,并放在canvas画布上,然后使用canvas.toDataURL将画布中的内容进行输出,该方法接受两个参数,分别是输出格式压缩比例

四、将压缩后的数据进行操作就好了

完整代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <input id="ipt" type="file" accept="image/jpg, image/png, image/jpeg" />
    <p id="exponent"></p>
    <script>
        //选取DOM元素
        const ipt = document.getElementById("ipt");
        const exp = document.getElementById("exponent")
        //设置图片最大上传尺寸,根据需求来,这里设置为最大1M
        const MAXSIZE = 1024 * 1024;
        //监听input的change事件
        ipt.addEventListener('change', (e) => {
            const [file] = e.target.files; //可以获得上传的文件信息
            if(!file) {
                return
            }
            const {type:fileType, size:fileSize} = file; //得到上传文件的大小和类型
            //图片压缩处理
            convertImageToBase64(file,(base64Image) => compress(base64Image,uploadImage));
        })
        //首先将图片转为base64格式,两个参数,需要转换的文件 回调函数
        function convertImageToBase64(file,callback) {
            let reader = new FileReader();
            reader.addEventListener('load' , (e) => {
               const base64Image = e.target.result  //这里是得到的base64数据
                callback && callback(base64Image); //回调函数去处理得到的base64数据
                reader = null;  //将reader指向null,便于浏览器回收
            })
            reader.readAsDataURL(file);
        }
        //对base64数据进行压缩的函数
        function compress(base64Image,callback) {
            //设置图片的最大宽和高,根据实际需求来定
            let maxW = 1024;
            let maxH = 1024;
            //将得到的base64数据赋值给一个图片对象,以获得图片的宽高
            const image = new Image();
            image.addEventListener('load', (e) => {
                let ratio; //图片压缩比
                let needCompress = false; //是否需要压缩
                //maxW < 图片实际宽度时走这里
                if(maxW < image.naturalWidth) {   //image.naturalWidth获取图片实际宽度
                    needCompress = true;  //需要压缩
                    ratio = image.naturalWidth / maxW;  //得到压缩比例
                    maxH = image.naturalHeight / ratio; //同比缩放maxH
                }   
                //maxH < 图片实际高度时走这里
                if(maxH < image.naturalHeight) {
                    needCompress = true;
                    ratio = image.naturalHeight / maxH;
                    maxW = image.naturalWidth / ratio;
                }
                if(!needCompress) {   //不需要压缩时,将图片宽高赋值给maxW和maxH
                    maxW = image.naturalWidth;
                    maxH = image.naturalHeight;
                }
                const canvas = document.createElement('canvas');
                canvas.setAttribute('id', '_compress');
                canvas.width = maxW;
                canvas.height = maxH;
                canvas.style.visibility = 'hidden';
                document.body.appendChild(canvas);

                const ctx = canvas.getContext('2d');
                ctx.clearRect(0, 0, maxW, maxH);  //先清掉画布,再绘制新的内容
                ctx.drawImage(image, 0, 0, maxW, maxH); //绘制图片
                const compressImage = canvas.toDataURL('image/jpeg', 0.9); //将图片输出
                const _image = new Image();
                _image.src= compressImage;
                document.body.appendChild(_image);
                const compressRatio = image.src.length / _image.src.length;
                exp.innerText = `压缩比为:${compressRatio}`
                callback && callback(compressImage);  //拿出压缩后的图片,进行上传等操作
                canvas.remove();
            })
            image.src= base64Image;
            image.src && document.body.append(image);
        }
        function uploadImage(file) {  //对压缩后的数据进行操作
            console.log(file);
        }
    </script>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值