项目实践后的图片压缩完整使用过程【vue3+js】

van-uploader + 图片压缩 + 图片base64转成file

 compressImage.js

const ACCEPT = ['image/jpg', 'image/png', 'image/jpeg']
const MAXSIZE = 1024 * 1024 * 2;
const MAXTIP = "4"

// 压缩算法函数
/* 
1.首先拿到了base64的图片字符串 
2.创建一个image对象,获得原始图片的宽度和高度
3.对原始图片的宽度和高度进行压缩达到符合条件(第一次压缩-从尺寸压缩)
4.调用canvasAPI进行绘制新的图片
5.绘制成功之后调用canvasAPI进行绘制(canvasAPI支持压缩-二次压缩-从质量压缩)
6.得到压缩后的base64
 */
function compress(base64Image, file, callback) {
    let maxW = 1024;
    let maxH = 1024;
    const image = new Image() // 创建image对象 相当于创建a标签
    image.addEventListener('load', function (e) {
        // image加载完成后就会触发 也就是src加载后
        let radio; // 压缩比例
        let needCompress = false; // 是否需要压缩
        if (file.file.size > MAXSIZE) {
            needCompress = true;
            // 获得压缩宽高过后的大小(保证等比例缩放)
            radio = image.naturalWidth / maxW
            maxH = image.naturalHeight / radio
        }
        // 不需要压缩
        if (!needCompress) {
            maxW = image.naturalWidth;
            maxH = image.naturalHeight;
        }
        // 第一次压缩完成
        // 接下来使用canvas进行质量压缩
        const canvas = document.createElement('canvas')
        canvas.height = maxH;
        canvas.width = maxW;
        canvas.setAttribute("id", "_compress_")
        // visibility hidden 需要创建的canvas隐藏 而不是不渲染DOM
        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)
        // 接来下就是压缩canvas 通过API将canvas输出成base64格式

        const compressImage = canvas.toDataURL('image/jpeg', 0.8) // 通常压缩是0.8-0.9
        callback && callback(compressImage); // 压缩完成进行后台传输逻辑
        canvas.remove()

    })
    image.src = base64Image;
    // document.body.appendChild(image) // 挂载

}

function imgbase64Tofile(base64, fileName) {
    // 将base64按照 , 进行分割 将前缀  与后续内容分隔开
    let data = base64.split(',');
    // 利用正则表达式 从前缀中获取图片的类型信息(image/png、image/jpeg、image/webp等)
    let type = data[0].match(/:(.*?);/)[1];
    // 从图片的类型信息中 获取具体的文件格式后缀(png、jpeg、webp)
    let suffix = type.split('/')[1];
    // 使用atob()对base64数据进行解码  结果是一个文件数据流 以字符串的格式输出
    const bstr = window.atob(data[1]);
    // 获取解码结果字符串的长度
    let n = bstr.length
    // 根据解码结果字符串的长度创建一个等长的整形数字数组
    // 但在创建时 所有元素初始值都为 0
    const u8arr = new Uint8Array(n)
    // 将整形数组的每个元素填充为解码结果字符串对应位置字符的UTF-16 编码单元
    while (n--) {
        // charCodeAt():获取给定索引处字符对应的 UTF-16 代码单元
        u8arr[n] = bstr.charCodeAt(n)
    }
    // 利用构造函数创建File文件对象
    // new File(bits, name, options)
    const time = (new Date()).valueOf()
    const file = new File([u8arr], `${fileName}${time}.${suffix}`, {
        type: type
    })
    // 将File文件对象返回给方法的调用者
    return file;
}

export default { compress, imgbase64Tofile }

main.js

import compressImage from './utils/compressImage';
app.config.globalProperties.$compressImage = compressImage;
上传页面
 <van-uploader
                            :before-read="beforeRead"
                            :after-read="afterRead1"
                            :before-delete="beforeDelete1"
                            accept="image/*"
                            :max-count="1"
                            v-model="fileList1"
                            :max-size="maxSize"
                            image-fit="contain"
                            @oversize="onOversize" >
                            <div class="img_box upload_box1"></div>
</van-uploader>
<script setup>
   import { ref, reactive,getCurrentInstance} from 'vue'
   const { proxy } = getCurrentInstance()
const fileList1 = ref([]);
const maxSize = ref(1024 *1024 * 4)
const beforeRead = (file)=> {// 上传身份证图片前的图片格式校验
  if (file.type !== 'image/jpeg' && file.type !== 'imagepng' && file.type !== 'image/jpg') {
        Toast.fail('请上传jpg或jpeg或png的格式图片');
    return false;
  } else {
    return true;
  }
}
const afterRead1 = (file)=> {
    // 调用身份证图文识别接口
    proxy.$compressImage.compress(file.content,file,(base64)=>{
        proxy.$compressImage.imgbase64Tofile(base64,'idcardfront')
    })
}
const onOversize = (file) => {//上传图片过大提示
  Toast('文件大小不能超过4M');
};
// 删除上传的文件
const beforeDelete1= (file)=>{
    fileList1.value = []
    delete idcardMsg.ID_Cardname
    delete idcardMsg.ID_Idno
}

</script>

 

  

    
posted @ 2023-04-04 15:03  小那  阅读(417)  评论(0编辑  收藏  举报