一只特立独行的猪 一只特立独行的🐷
一只特立独行的🐷
  • 主页
  • web开发
  • 博客笔记
  • 软件工具
  • 随笔杂谈
  • 文章归档
  • 影音欣赏
  • 我的资源
  • 关于我
  • wechat_fill

Wing主题上传前压缩解决图片过大的问题

  • 2023-02-23
  • 博客笔记
  • 评论(6)

压缩方法参考:https://juejin.cn/post/6940430496128040967

大家可以持续关注我的系列优化文章
Wing主题优化记录

背景

wing主题默认说说的图片上传是原图上传到了wp的素材库,手机发布的时候一般选择随手拍的照片,得益手机越来越好的像素,原图都非常大,首页大图多了,会严重拖慢首页的加载速度,像我这个个人的小水管服务器根本受不了,效果如下,加载很影响体验
file

而我本身并没有在博客发布原图的诉求,所以得想个办法解决一下

前端压缩

本来想着可以在后端存储的时候压缩一下,存储一下多倍图,前端可以选择压缩后的图输出,想了一下我完全没有在博客存储原图的诉求,所以直接在前端上传前压缩吧,还能提升上传的速度
直接放代码:https://github.com/moxiaonai/Wing-magic/blob/main/static/modules.js#L295

/**
             * 压缩图片方法
             * @param {file} file 文件
             * @param {Number} quality 图片质量(取值0-1之间默认0.92)
             */
            compressImg(file, quality) {
                var qualitys = 0.52
                if (parseInt((file.size / 1024).toFixed(2)) < 1024) {
                    qualitys = 0.85
                }
                if (5 * 1024 < parseInt((file.size / 1024).toFixed(2))) {
                    qualitys = 0.92
                }
                if (quality) {
                    qualitys = quality
                }
                if (file[0]) {
                        return Promise.all(Array.from(file).map(e => this.compressImg(e, qualitys))) // 如果是 file 数组返回 Promise 数组
                } else {
                    return new Promise((resolve) => {
                        if ((file.size / 1024).toFixed(2) < 300) {
                            resolve(file)
                        } else {
                        const reader = new FileReader() // 创建 FileReader
                        reader.onload = ({
                            target: {
                            result: src
                            }
                        }) => {
                            const image = new Image() // 创建 img 元素
                            image.onload = async() => {
                                const canvas = document.createElement('canvas') // 创建 canvas 元素
                                const context = canvas.getContext('2d')
                                var targetWidth = image.width
                                var targetHeight = image.height
                                var originWidth = image.width
                                var originHeight = image.height
                                if (1 * 1024 <= parseInt((file.size / 1024).toFixed(2)) && parseInt((file.size / 1024).toFixed(2)) <= 10 * 1024) {
                                    var maxWidth = 1600
                                    var maxHeight = 1600
                                    targetWidth = originWidth
                                    targetHeight = originHeight
                                    // 图片尺寸超过的限制
                                    if (originWidth > maxWidth || originHeight > maxHeight) {
                                    if (originWidth / originHeight > maxWidth / maxHeight) {
                                        // 更宽,按照宽度限定尺寸
                                        targetWidth = maxWidth
                                        targetHeight = Math.round(maxWidth * (originHeight / originWidth))
                                    } else {
                                        targetHeight = maxHeight
                                        targetWidth = Math.round(maxHeight * (originWidth / originHeight))
                                    }
                                    }
                                }
                                if (10 * 1024 <= parseInt((file.size / 1024).toFixed(2)) && parseInt((file.size / 1024).toFixed(2)) <= 20 * 1024) {
                                    maxWidth = 1400
                                    maxHeight = 1400
                                    targetWidth = originWidth
                                    targetHeight = originHeight
                                    // 图片尺寸超过的限制
                                    if (originWidth > maxWidth || originHeight > maxHeight) {
                                    if (originWidth / originHeight > maxWidth / maxHeight) {
                                        // 更宽,按照宽度限定尺寸
                                        targetWidth = maxWidth
                                        targetHeight = Math.round(maxWidth * (originHeight / originWidth))
                                    } else {
                                        targetHeight = maxHeight
                                        targetWidth = Math.round(maxHeight * (originWidth / originHeight))
                                    }
                                    }
                                }
                                canvas.width = targetWidth
                                canvas.height = targetHeight
                                context.clearRect(0, 0, targetWidth, targetHeight)
                                context.drawImage(image, 0, 0, targetWidth, targetHeight) // 绘制 canvas
                                const extType = file.type
                                const canvasURL = canvas.toDataURL(extType, qualitys)
                                const buffer = atob(canvasURL.split(',')[1])
                                let length = buffer.length
                                const bufferArray = new Uint8Array(new ArrayBuffer(length))
                                while (length--) {
                                    bufferArray[length] = buffer.charCodeAt(length)
                                }
                                const miniFile = new File([bufferArray], file.name, {
                                    type: extType
                                })
                                console.log({
                                    file: miniFile,
                                    origin: file,
                                    beforeSrc: src,
                                    afterSrc: canvasURL,
                                    beforeKB: Number((file.size / 1024).toFixed(2)),
                                    afterKB: Number((miniFile.size / 1024).toFixed(2)),
                                    qualitys: qualitys
                                })
                                resolve(miniFile)
                            }
                            image.src = src
                        }
                            reader.readAsDataURL(file)
                        }
                    })
                }
            },

使用:

 async handleUpload(e) {
                const { files } = (e.target || {});
                const len = { flag: 0, count: files.length };
                this.uploading = true;
                const imgs = await this.compressImg(files)
                Array.from(imgs).forEach(file => {
                    const formData = new FormData();
                    formData.append("file", file);
                    file.id = Math.random().toString(32).substring(2);
                    this.files.push({ id: file?.id, source_url: file.name, loading: true });
                    $h.rest('wp/v2/media', {
                        method: 'POST',
                        headers: {
                            'Content-Type': null,
                            'Content-Disposition': `attachment; filename=${encodeURI(file.name)}`
                        },
                        body: formData,
                    }).then(({ id, guid, mime_type }) => {
                        if(id) {
                            // 根据id替换
                            this.files = this.files.map(item => {
                                if ( item.id === file.id ) {
                                    item = { id, source_url: guid.raw, mime_type, loading: false };
                                }
                                return item;
                            });
                        }
                    }).finally(() => {
                        if ( ++len.flag === len.count ) {
                            this.uploading = false;
                        }
                    }).catch(err=>{
                        this.files.pop();
                    })
                });
                e.target.value = ""; // 清空input
            },

可以根据需要调整quality,目前的参数是经过大佬调整多轮后的最优解了,原方案里面图片类型我做了调整,压缩图片继承原图片格式类型const extType = file.type,如果需要统一转成png或者其他格式,这里可以设置为固定值

至此,体验终于好了很多!

Powered by Wordpress, Theme by Wing-magic
©2023 一只特立独行的🐷 All rights reserved
陕ICP备15006707号-5