图片压缩在前端开发日常中的使用频率实在是太高了,使用得最高的就是tinypng但是它有限制,就想着能不能搞个没有限制的图片压缩工具出来。
然后在掘金上找技术方案看到了大佬粥里有勺糖
的文章纯前端实现 JPG 图片压缩 | canvas - 掘金 (juejin.cn),技术上是已经完全通了,怎样把它做成一个好看好用的产品呢,于是就模仿tinypng的UI,用electron打包成了一个可以在业务场景下正常使用的产品。
产品效果
技术栈
vue3 electron
选择文件后的处理
这里的压缩其实只对png和jpg做了处理,并加了熊猫的状态变化,处理中的时候上坐着的,处理成功后熊猫就开心的站起来了
async function changeFile(event) {
happy.value = false;
// 取出原始文件,取出不同项
const differentItems = [...event.target.files].filter((item1) => {
return !org_files.value.some((item2) => {
let bol = item2.size == item1.size && item2.name == item1.name;
return bol;
});
});
org_files.value = [...org_files.value, ...differentItems];
let compressedFile = null;
// 遍历压缩
differentItems.forEach(async (file, i) => {
if (await isPNG(file)) {
compressedFile = await compressPNGImage(file, {
quality: 1,
noCompressIfLarger: true,
});
}else {
compressedFile = await compressJPGImage(
file,
"browser-image-compression",
{
quality: 1,
noCompressIfLarger: true,
}
);
}
compressedFile.org_size = differentItems[i].size;
comp_files.value.push(compressedFile);
});
event.srcElement.value = null;
setTimeout(() => {
calcTotal();
}, 500);
}
统计压缩比率
function calcTotal() {
let total_org = 0;
let total_comp = 0;
comp_files.value.forEach((item) => {
total_org += item.org_size;
total_comp += item.size;
});
total.value = Number.parseInt(((total_org - total_comp) / total_org) * 100);
saveSpace.value = formatSize(total_org - total_comp);
happy.value = true;
}
全部下载转zip
function downAll() {
const zip = new JSZip();
// 将每个 File 对象添加到 zip 文件中
comp_files.value.forEach((file, index) => {
zip.file(file.name, file);
});
// 生成 zip 文件
zip.generateAsync({ type: "blob" }).then((content) => {
downloadFile(content, `TinyJpg${new Date().getTime()}.zip`);
});
}