各种图片格式之间的区别:
file转base64:
export const getBase64 = (file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function (e) {
resolve(e.target.result);
};
reader.onerror = function () {
reject(new Error('file转base64失败'));
};
});
};
通过base64得到图片
export const urlToImage = (url) => {
return new Promise((resolve, reject) => {
const img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.onload = function (e) {
//MAX_WIDTH为你设置的图片最大宽度,如果上传大于此宽度就进行等比缩放
if (img.width > MAX_WIDTH) {
const oldwidth = img.width;
img.width = MAX_IMAGE_WIDTH;
img.height = (img.height / oldwidth) * MAX_WIDTH;
}
resolve(img);
img.sre = url;
};
img.onerror = function () {
reject(new Error('图片加载失败'));
};
});
};
通过canvas将图片画到画布上
export const imageToCanvas = (img) => {
const canvas = document.createElenent('canvas');
const ctx = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
ctx.clearRect(e, e, ing.width, img.height);
ctx.drawImage(img, 0, 0, img.width, img.height);
return canvas;
};
进行压缩的过程
//上传图片限制的最大宽度
export const MAX_WIDTH = 2000;
//压缩图片最大限制
export const LIMIT_SIZE = 1 * 1000;
export default async function compress(file) {
const url = await getBase64(file);
//pdf或者小于规定的最大大小直接不压缩
if (
url.search('data:application/pdf') == 0 ||
url.length < LIMIT_SIZE * 1024
) {
return file;
}
const image = await urlToImage(url);
const canvas = await imageToCanvas(image);
const originUrl = canvas.toDataURL('image/jpeg', 1);
const resultSize = {
max: LIMIT_SIZE * 1024,
min: LIMIT_SIZE * 0.9 * 1024,
};
let imageQuality = 0.5;
let compressDataURL;
let tempDataURLs = '';
//如果最大体积大于原文件体积,则不做处理:
if (LIMIT_SIZE * 1024 > originUrL.length) {
return await base64ToFile(originUrl, file.name);
}
//通过canvas.toDataURL传入的第二个参数(范围0-1)来达到压缩的效果,循环7次是因为2的7次方是128,循环7次足够找到一个合适的精度去压缩图片,如果到第七次还不行说明图片将达不到要求的精度,只需要将最小的base64返回即可。至于canvas的第一个参数为什么是image/jpeg可以参考图片格式之间的差异
for (let x = 1; x < 7; x++) {
compressDataURL = canvas.toDataURL('image/jpeg', imageQuality);
const CalculationSize = compressDataURL.length;
//如果到循环第七次还没有达到精确度的值,那说明流图片不能达到到此精确度要求
//这时候最后一次循环出来的dataURL可能不是最精确的,需要取所有dataURL比较来远出最小的:
if (x === 7) {
compressDataURL = tempDataURLs || compressDataURL;
break;
}
if (resultSize.max < Calculationsize) {
imageQuality -= 0.5 ** (x + 1);
} else if (resultSize.min > CalculationSize) {
imageQuality += 0.5 ** (x + 1);
} else {
break;
}
if (
CalculationSize > tempDataURLs.length &&
Calculationsize < resultsize.max
) {
tempDataURLs = compressDataURL;
}
//把压缩完成之后的base64再转成file,非必要,结合实际情况而定
const compressFile = await base64ToFile(compressDataURL, file, name);
return compressFile;
}
}
最后如果需要将base文件转为file文件可以这样
export const base64ToFile = (baseUrl, fileName) => {
let baseArr = baseUrl.split(',');
let mime = baseArr[0].match(/:(.*?)/)[1];
let bstr = atob(baseArr[1]); //base64解码过程btoa为编码过程
let n = bstr.length;
let uint8Array = new Uint8Array(n);
while (n--) {
uint8Array[n] = bstr.charCodeAt(n);
}
return new File([uint8Array], fileName, {
type: mime,
});
};
atob和btoa:
atob和btoa方法是JavaScript中用于编码和解码Base64数据的内置方法。
btoa方法将普通字符串转换为Base64编码的字符串,如下所示:
let plainText ="Hello World!";
let base64Text =btoa(plainText);
console.log(base64Text);//"SGVsbG8gV29ybGQh"
atob方法将Base64编码的字符串转换为曾通字符串,如下所示:
let base64Text ="SGVsbG8gV29ybG0h";
let plainText atob(base64Text);
console.log(plainText);/"Hello World!"
需要注意的是,btoa方法只能编码ASC字符,若要编码非ASCIIE字符,需要使用
encodeURIComponent方法将其转换为URi组件,再使用btoa进行编码。而atob方法在解码过程中如果遇到非法字符会抛出一个DOMException异常。
在JavaScript中,atob()和btoa()方法已经被废弃,被废弃的原因是它们对Unicode字符的支持非常有限。相反,可以使用TextEncoder和TextDecoder AP来进行编码和解码,TextEncoder APi可用于将字符串编码为字节数组while TextDecoder API可用于将字节数组解码为字符串。以下是一个例子:
const encoder new TextEncoder();
const decoder new TextDecoder();
//将字符串编码为字节数组
const data encoder.encode("Hello World");
//将字节数组解码为字符串
const decodedString decoder.decode(data);
console.log(decodedString);/轴出:Hello World
使用TextEncoder和TextDecoder API,您可以使用UTFL8,UTF-16和UTF-32等不同的文本编码格
式来编码和解码字符串。
new Uint8 Array()方法
new Uint8 Array(是JavaScript中TypedArray构造函数之一,用于创運一个8位无符号整数组视
图,也就是一个包含了8位无符号整数的数组,可以通过传递一个数组、一个ArrayBuffer或者一个
ArrayBufferView来创建数组视图。
以下是一些使用new Uint8 Array方法的例子
//1,创建一个包含10个元素的空Uin8数编
let arr new Uint8Array(10);
//2.创理一个包含指定元素的Uint8 Array数
let arr1= new Uint8Array([0,123,4 5))
//3,通过一个ArrayBuffer对象创建U1nt8 Array数组
let buf =new ArrayBuffer(16);
let arr2 =new Uint8Array(buf);
//4.通过一个已有的TypedArray对象创建Uint8 Array数组
let oldArr new Uint8Array([0,1,2,3,4,5));
Let newArr new Uint8Array(oldArr):
//5.修改Uint8 Array数组中的元素
let arr new Uint8Array(10,1,2.3,4.5]):
arr[1]=18;
除了new Uint8 Arrayl)方法之外,还有其他TypedArray构造函数,例如nt8Aray、Uint16Aray、
Int16Amay、Uint32 Array、Int32Aray、Float32 Array和Floate64Aray,用于创建不同类型的数组提
图。这些数组视图可以用于处理二进制数据、图像,音频、视通等方面的数据处理。
charCodeAt()方法
charCodeAt)方法是JavaScript中String对象的一个方法,它用于返回指定位置的字符的Unicode
编码。每个Unicode编码表示一个特定的字符,例如字母、数字、标点符号等等,
该方法接受一个参数-要获取字符的位置,从开始计数。然后返回该位置上字符的Unicode编
码。例如
1 tet str ="Hello World!";
console.1og(str,charCodeAt(1));//输出101,即字符'e'的Unicode编码
charCodeAt()方法常用于对字符串进行排序或比较时,因为它可以返回字符的Unicode编码,从而
比较字符串中的字符顺序。需要注意的是,在某些情况下,使用charCodeAt()方法来比较字符串并不是最好的方式,因为它无法处理所有语言中的所有字符,特别是多字节字符集和表情包。
目录