canvas重绘图片达到压缩目的

直接贴代码

封装一个方法

/**
 * @param { * } file input选择后返回的file对象
 */
 export const compressImage = (file) => {
    // 参数file,是通过input 选择本地文件获取的
    return new Promise((resolve, reject) => {
        let img = new Image();

        // 创建一个reader实例
        let reader = new FileReader();

        // 读取拿到的文件
        reader.readAsDataURL(file);
        reader.onload = (e) => {
            // 文件加载成功后去转成Img对象,为了拿到图片的原始宽高
            img.src = e.target.result;
            img.onload = () => {
                let compressRadio = 0.1  //自定义文件压缩程度,0-1之间

                // 创建画布canvas
                let canvas = document.createElement("canvas");
                let context = canvas.getContext("2d");

                // 获取文件宽高
                const { width: originWidth, height: originHeight } = img

                // 自定义等比例缩放宽高属性
                const scale = +(originWidth / originHeight).toFixed(2) // 计算出缩放比例,取小数点后两位
                const targetWidth = originWidth * compressRadio // 计算图片压缩的目标宽度
                const targetHeight = Math.round( targetWidth / scale ) // 根据目标宽度计算图片压缩后的高度
            
                // 设置画布宽高
                canvas.width = targetWidth
                canvas.height = targetHeight

                // 先清除画布
                context.clearRect(0, 0, targetWidth, targetHeight)
                // canvas重新绘制图片
                context.drawImage(img, 0, 0, targetWidth, targetHeight)
                // 获取原文件类型
                const fileType = `image/${file.type.split("/")[1]}` || 'image/png'

                // 返回形式1:以file对象形式返回。
                // blob 格式的图片 转成file对象(即canvas转二进制对象转文件对象)
                canvas.toBlob((blob) => {
                     const theFile = new File([blob], file.name, {type: fileType, lastModified: file.lastModified})
                     resolve({ type: fileType, compressedFile: theFile });
                }, fileType)

                //返回形式2:以base64编码格式返回。可直接用img标签展示
                // let vagueRadio = 0.8  //自定义图片质量,0-1之间,默认0.92
                // const base64Url = canvas.toDataURL(fileType, vagueRadio)  //转为base64,返回
                // resolve({ base64Url: base64Url })
            };
        };
    });
};

如何使用

<input type="file" accept="image/*" multiple @change="selectImg($event)">


import { compressImage } from '@/utils/imgCompress'

//如果以file格式返回
selectImg (e) {
        const file = e.target.files[0]
        if (!file.type.startsWith('image/')){
            this.$message.warning('请勿上传图片以外的文件')
            return
        }
        compressImage(file).then(res=>{
            if (res.compressedFile) {
                const formData = new FormData()
                formData.append('file', res.compressedFile)
                //将 formData 传至接口即可
            }
        })
    },

//如果以base64格式返回
selectImg (e) {
        const file = e.target.files[0]
        if (!file.type.startsWith('image/')){
            this.$message.warning('请勿上传图片以外的文件')
            return
        }
        compressImage(file).then(res=>{
            if (res.base64Url) {
                this.imgUrl = res.base64Url
                //res.base64Url可直接在img标签中展示
            }
        })
    },

图示

posted @ 2022-11-09 14:16  huihuihero  阅读(94)  评论(0编辑  收藏  举报