前言

最近在使用vant的uploader组件做照片上传的时候碰到了一个问题,拍摄的照片文件过大导致后台接口一直报错,所以后端期望我前端上传之前先给压缩一下。

前端压缩的话,目前我只能想到等比例缩小图片原始宽高的方法,后面如果接触到更好的方法我再更新。

源码

export default function () {
    // file是图片的base64码,必填
    // width是压缩后的图片宽度,选填,默认值700
    let compressImage = (file, width) => {
        return new Promise((resolve) => {
            // 新建一个img标签(不嵌入DOM节点,仅做canvas操作),src需要传入base64
            let image = new Image()
            image.src = file

            // 图片加载完毕后再通过canvas压缩图片(图片还没加载完就压缩,有可能得到一张全黑的图片)
            image.onload = function () {
                let canvas = document.createElement("canvas")
                let context = canvas.getContext("2d")

                // 获取图片原始宽高
                let canvasWidth = image.width;
                let canvasHeight = image.height;

                // 获取图片原始宽高比
                let sizeRatio = canvasWidth / canvasHeight;

                // 固定宽,按原始宽高比压缩图片
                let newWidth
                width ? newWidth = width : newWidth = 700
                if (canvasWidth > newWidth) {
                    canvasWidth = newWidth;
                    canvasHeight = Math.floor(canvasWidth / sizeRatio);
                }

                // 压缩后设置宽高
                canvas.width = canvasWidth
                canvas.height = canvasHeight

                // 使用drawImage重新设置img标签中的图片大小,实现压缩。
                context.drawImage(image, 0, 0, canvasWidth, canvasHeight)

                // 使用toDataURL将canvas上的图片转换为base64格式
                let newFile = canvas.toDataURL("image/jpeg")

                resolve(newFile)
            }
        })
    }

    return {
        compressImage,
    }
}

使用方法

import useUploadImage from "../../hooks/useUploadImage";

export default {
    name: "Demo",
    setup() {
        let {compressImage} = useUploadImage()
        
        let uploadAvatar = (file) => {
            // 默认宽
            compressImage(file.content).then((newFile) => {
                // newFile就是压缩过后图片的base64码
            })
            
            // 自定义宽
            compressImage(file.content, 500).then((newFile) => {
                // newFile就是压缩过后图片的base64码
            })
        }

        return {
            uploadAvatar
        }
    },
}