跳到主要内容

Canvas

2024年06月18日
柏拉文
越努力,越幸运

一、认识


  1. input 读取到 文件 ,使用 FileReader 将其转换为 base64 编码
  2. 新建 img ,使其 src 指向刚刚的 base64
  3. 新建 canvas ,将 img 画到 canvas 上
  4. 利用 canvas.toDataURL/toBlob 将 canvas 导出为 base64 或 Blob
  5. 将 base64 或 Blob 转化为 File

二、实现


<template>
<div class="compress">
<input type="file" @change="selectImg" multiple />
</div>
</template>

<script>
import { defineComponent } from 'vue';
export default defineComponent({
methods: {
/**
* @description: 选择图片
* @param {*} e 文件对象
*/
async selectImg(e) {
const { files } = e.target;
const result = await this.compressImg(files, 0.2);
console.log(result);
},
/**
* @description: 压缩图片
* @param {*} file 文件对象
* @param {*} quality 图片质量
*/
compressImg(file, quality) {
if (file[0]) {
/**
* @description: 如果 file[0] 成立,说明传入的是 file 数组,对 file 中的每一个文件处理
*/
return Promise.all(Array.from(file).map(item => this.compressImg(item, quality)));
} else {
/**
* @description:对单个文件进行压缩处理
*/
return new Promise(resolve => {
const fileReader = new FileReader();
fileReader.onload = ({ target: { result: src } }) => {
const img = new Image(); //创建 图片 对象
img.onload = () => {
/**
* @description: 图片加载完成后
*/
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, img.width, img.height);
/**
* @description: 获取压缩图片的 Base64 格式
* * quality: 当quality在0.2~0.5之间,图片质量变化并不大,quality的值越小,压缩效率越可观
*/
const canvasURL = canvas.toDataURL('image/jpeg', quality);
/**
* @description: 通过压缩图片的 Base64 格式转化为 压缩图片的 File 对象
*/
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 compressFile = new File([bufferArray], file.name, {
type: 'image/jpeg',
});
/**
* @description: 返回 压缩前图片信息 和 压缩后图片信息
*/
resolve({
compressBefore: {
file: file,
url: src,
size: Number((file.size / 1024).toFixed(2)),
},
compressAfter: {
file: compressFile,
url: canvasURL,
size: Number((compressFile.size / 1024).toFixed(2)),
},
});
};
img.src = src; //图片对象赋值
};
fileReader.readAsDataURL(file);
});
}
},
},
});
</script>

<style scoped></style>