图片文件压缩成指定尺寸并返回base64 格式
1.因业务需求要求前端直接上传base64 图片格式 并大小不能超过2mb
2.网上也有很多相关压缩npm包,直接用对自己技术没啥提升。
然后就手搓了一个压缩图片,代码如下:
/**
* 符合封闭开放原则
* 封闭FileMethod
* 开放FileExecute
*/
/** 文件方法合集 不用看,不要修改 FileMethod 中的方法 */
class FileMethod {
/**
* @param path 路径转ImageNode
* @returns Image
*/
protected static pathShiftImageNode(path: string): Promise<any> {
return new Promise((resolve, reject) => {
const img = new Image()
img.src = path
img.setAttribute("crossOrigin", 'anonymous')//设置图片跨域属性
img.onload = (e) => {
let target = e.target;
resolve(target)
}
img.onerror = reject
})
}
/**
* @param file 需要转换的文件
* @returns [base64,target,node]
*/
protected static fileShiftBase64(file: File): Promise<any[]> {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.readAsDataURL(file)
function load(node: any) {
resolve([node?.target?.result, node?.target, node])
}
reader.onload = load
reader.onerror = reject
})
}
/**
*
* @param img img图片元素
* @param targetWidth 渲染显示出来的目标图片宽
* @param targetHeight 渲染显示出来的目标图片高
* @returns canvas 返回canvas元素
*/
protected static rendererCanvas(img: HTMLImageElement, targetWidth: number, targetHeight: number): HTMLCanvasElement {
// 创建画布
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d');
// 设置宽高度为等同于要压缩图片的尺寸
canvas.width = targetWidth;
canvas.height = targetHeight;
context?.clearRect(0, 0, targetWidth, targetHeight);
context?.drawImage(img, 0, 0, targetWidth, targetHeight)
return canvas
}
/**
* @param img 根据图片元素动态计算出适合压缩的图片尺寸
* @returns { img: HTMLImageElement, targetWidth: number, targetHeight: number }
*/
protected static ImageFitSize(targetImg: HTMLImageElement, maxWidth = 1000, maxHeight = 1000)
: { targetImg: HTMLImageElement, targetWidth: number, targetHeight: number } {
const { width: originWidth, height: originHeight } = targetImg;
let targetWidth = originWidth;
let targetHeight = originHeight;
if (originWidth > maxWidth || originHeight > maxHeight) {
if (originWidth / originHeight > 1) {
// 宽图片
targetWidth = maxWidth
targetHeight = Math.round(maxWidth * (originHeight / originWidth))
} else {
// 高图片
targetHeight = maxHeight
targetWidth = Math.round(maxHeight * (originWidth / originHeight))
}
}
return { targetImg, targetWidth, targetHeight }
}
}
/** 业务执行逻辑 可根据业务需求进行自定义修改 */
class FileExecute extends FileMethod {
/**
* @function 压缩图片文件的方法 压缩成指定尺寸大小并返回 base64 格式
* @describe 图片文件 压缩成指定尺寸大小并返回 base64 格式
* @param file 需要压缩的图片文件
* @param {
* maxWidth = 1000,最大宽
* maxHeight = 1000,最大高
* quality = 0.5 ,图片质量,指定图片格式为 image/jpeg 或 image/webp的情况下,可以从 0 到 1 的区间内选择图片的
* imageType = 'image/jpeg'
* }
* @returns { base64 返回压缩后的base64字符串 , canvas HTMLCanvasElement }
*/
static async compressImageFile(file: File, {
maxWidth = 1000,
maxHeight = 1000,
quality = 0.5,
imageType = 'image/jpeg'
}): Promise<{ base64: string, canvas: HTMLCanvasElement }> {
let [base64] = await FileExecute.fileShiftBase64(file)
let image = await FileExecute.pathShiftImageNode(base64)
let { targetImg, targetWidth, targetHeight } = FileExecute.ImageFitSize(image, maxWidth, maxHeight)
//渲染Canvas成指定大小
let canvas = FileExecute.rendererCanvas(targetImg, targetWidth, targetHeight)
//返回原生HTMLCanvas 可根据原生方法 进行自定义
return { base64: canvas.toDataURL(imageType, quality), canvas: canvas }
}
}
export default FileExecute
1.根据封闭开放原则 ,封闭FileMethod,开放FileExecute 可根据相关业务修改。
把图片文件压缩成指定尺寸大小
用法:
import { FileExecute } from './fileExecute'
//示例 imageFile 为图片文件
const Test = (imageFile)=>{
let { base64, canvas } = await FileExecute.compressImageFile(imageFile,{
maxWidth = 1000, //设置最大宽
maxHeight = 1000,//设置最大高
quality = 0.5, //设置图片质量 0 ~ 1
imageType = 'image/jpeg'//设置图片格式
})
}