主题
图片压缩
h5
js
const compressImg = file => {
var files
var fileSize = parseFloat(parseInt(file["size"]) / 1024 / 1024).toFixed(2)
var read = new FileReader()
read.readAsDataURL(file)
return new Promise(function (resolve, reject) {
read.onload = function (e) {
var img = new Image()
img.src = e.target.result
img.onload = function () {
// 默认按比例压缩
var w = img.width
var h = img.height
// 生成canvas
var canvas = document.createElement("canvas")
var ctx = canvas.getContext("2d")
var base64
// 创建属性节点
canvas.setAttribute("width", w)
canvas.setAttribute("height", h)
ctx.drawImage(img, 0, 0, w, h)
if (fileSize < 1) {
// 如果图片小于一兆 那么压缩0.5
base64 = canvas.toDataURL(file["type"], 0.5)
} else if (fileSize > 1 && fileSize < 2) {
// 如果图片大于1M并且小于2M 那么压缩0.5
base64 = canvas.toDataURL(file["type"], 0.5)
} else {
// 如果图片超过2m 那么压缩0.2
base64 = canvas.toDataURL(file["type"], 0.2)
}
// 回调函数返回file的值(将base64编码转成file)
files = dataURLtoFile(base64, file.name) // 如果后台接收类型为base64的话这一步可以省略
resolve(files)
}
}
})
}
// base64转码(压缩完成后的图片为base64编码,这个方法可以将base64编码转回file文件)
const dataURLtoFile = (dataurl, filename) => {
var arr = dataurl.split(",")
var mime = arr[0].match(/:(.*?);/)[1]
var bstr = atob(arr[1])
var n = bstr.length
var u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], filename, {
type: mime,
})
}
h5.html
ts
function compressImg(file, quality) {
var qualitys = 0.52
console.log(parseInt((file.size / 1024).toFixed(2)))
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 => {
console.log(file)
if ((file.size / 1024).toFixed(2) < 300) {
resolve({
file: 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 canvasURL = canvas.toDataURL("image/jpeg", 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: "image/jpeg",
})
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({
file: miniFile,
origin: file,
beforeSrc: src,
afterSrc: canvasURL,
beforeKB: Number((file.size / 1024).toFixed(2)),
afterKB: Number((miniFile.size / 1024).toFixed(2)),
})
}
image.src = src
}
reader.readAsDataURL(file)
}
})
}
}
ts
ts
const fileToDataURL = (file: Blob): Promise<any> => {
return new Promise(resolve => {
const reader = new FileReader()
reader.onloadend = e => resolve((e.target as FileReader).result)
reader.readAsDataURL(file)
})
}
const dataURLToImage = (dataURL: string): Promise<HTMLImageElement> => {
return new Promise(resolve => {
const img = new Image()
img.onload = () => resolve(img)
img.src = dataURL
})
}
const canvastoFile = (canvas: HTMLCanvasElement, type: string, quality: number): Promise<Blob | null> => {
return new Promise(resolve => canvas.toBlob(blob => resolve(blob), type, quality))
}
/**
* 图片压缩方法
* @param {Object} file 图片文件
* @param {String} type 想压缩成的文件类型
* @param {Nubmber} quality 压缩质量参数
* @returns 压缩后的新图片
*/
export const compressionFile = async (file, type = "image/jpeg", quality = 0.5) => {
const fileName = file.name
const canvas = document.createElement("canvas")
const context = canvas.getContext("2d") as CanvasRenderingContext2D
const base64 = await fileToDataURL(file)
const img = await dataURLToImage(base64)
canvas.width = img.width
canvas.height = img.height
context.clearRect(0, 0, img.width, img.height)
context.drawImage(img, 0, 0, img.width, img.height)
const blob = (await canvastoFile(canvas, type, quality)) as Blob // quality:0.5可根据实际情况计算
const newFile = await new File([blob], fileName, {
type: type,
})
return newFile
}