vue进行多图片上传、压缩、旋转、转blob格式、canvas绘制最后图片预览
vue进行多图片上传、压缩、旋转、转blob格式、canvas绘制最后图片预览
前言
最近项目需求需要进行多图片或者文件夹拖拽实现图片上传的功能,现在对功能整体逻辑进行介绍:
多图片或者单张图片进行拖拽 =》 图片进行压缩至224分辨率 =》通过AI接口返回图片需要旋转至正向的角度数 =》通过canvas绘制进行旋转操作 =》将canvas绘制的img图片进行toDataURL预览操作 =》将canvas绘制的blob格式的二进制数据和图片的路径传给后端进行保存
整个流程看着比较繁琐,但是图片处理的时间速度还是比较快,接下来直接上代码,文件夹和图片拖拽的代码后续再进行整理,这里直接对图片的file进行处理
多图片的file数据格式
base64Array发给AI返回旋转角度
base64Array,imgDomArray和blobArray的数据格式
// 这里的resizeImgs就是压缩图片的方法,这里的file数据格式在前面图片中
const { imgDomArray, base64Array, blobArray }= await resizeImgs(file, file.length)
// 接下来通过base64Array发给AI返回旋转角度,这里返回的数据格式在前面图片中
uploadList.forEach((item, index) => {
// 将需要旋转的canvans进行重新绘制,这里filpx的值不用理睬这是镜像的功能
if (item.rotate > 0) {
const canvas = document.createElement('canvas')
const { width, height } = getRotatedSizes({
width: imgDomArray[index].width,
height: imgDomArray[index].height,
degree: item.rotate,
})
canvas.width = width
canvas.height = height
const ctx = canvas.getContext('2d', { alpha: false })
ctx.translate(canvas.width / 2, canvas.height / 2)
ctx.rotate((item.rotate * Math.PI) / 180)
ctx.drawImage(imgDomArray[index], -imgDomArray[index].width / 2, -imgDomArray[index].height / 2)
base64Array[index] = canvas.toDataURL('image/jpeg', 0.92)
}
})
// 这个时候的base64Array里面的地址就可以直接放入你对应的img的src中了,后续我将blob格式的数据和路径发给了后端,这里base64Array,imgDomArray和blobArray的数据格式也在前面图片中
// resize图片至224分辨率
// 接收files数组与数组长度
// 返回base64数组、图片dom数组、blob数组
export const resizeImgs = (fileArray, len) => {
return new Promise((resolve) => {
const base64Array = [] // base64Array是用来存放canvas.toDataURL的图片地址数组
const imgDomArray = [] // imgDomArray是用来存放img的图片数组
const blobArray = [] // blobArray是用来存放canvas的toBlob的blob格式数据数组
let num = 0
for (let i = 0; i < len; i++) {
const img = new Image()
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d', { alpha: false })
img.onload = () => {
// 通过宽高的对比进行224分辨率的转换赋值给canvas
const ratio = img.width / img.height
const width = ratio >= 1 ? Math.floor(224 * ratio) : 224
const height = ratio >= 1 ? 224 : Math.floor(224 / ratio)
canvas.width = width
canvas.height = height
ctx.drawImage(img, 0, 0, width, height)
base64Array[i] = canvas.toDataURL('image/jpeg', 0.7)
imgDomArray[i] = img
URL.revokeObjectURL(img.src)
canvas.toBlob(
(blob) => {
blobArray[i] = blob
num++
// 当num为最后一个时,将三个数组返回出去通过promise
if (num === len) resolve({ base64Array, imgDomArray, blobArray })
},
'image/jpeg',
0.7
)
}
img.onerror = () => {
resolve()
}
img.src = URL.createObjectURL(fileArray[i])
}
})
}
// 矩形图片旋转后画布的宽高,这里是纯数学方法,建议直接复用
export const getRotatedSizes = ({ width, height, degree }) => {
degree = Math.abs(degree) % 180
if (degree === 90) {
return {
width: height,
height: width,
}
}
const arc = ((degree % 90) * Math.PI) / 180
const sinArc = Math.sin(arc)
const cosArc = Math.cos(arc)
const newWidth = width * cosArc + height * sinArc
const newHeight = width * sinArc + height * cosArc
if (degree > 90) {
return {
width: newHeight,
height: newWidth,
}
} else {
return {
width: newWidth,
height: newHeight,
}
}
}
接下来是一些上面部分api的介绍
createObjectURL(obj):返回一个URL 对象表示指定的 File 对象(生成blob:http://www.xxxx.com/xx的链接,可以直接在网页上打开File内容)或 Blob 对象(用于下载),obj为 File 对象、Blob 对象或者 MediaSource 对象
revokeObjectURL(objURL):在每次调用 createObjectURL() 方法时,都会创建一个新的 URL 对象,即使你已经用相同的对象作为参数创建过。当不再需要这些 URL 对象时,每个对象必须通过调用 URL.revokeObjectURL() 方法来释放,objURL为URL.createObjectURL(obj) 返回的对象
arr = new Uint8Array(length):返回一个长度为length的8位无符号整型数组(存储大小为0~256,负数会自动加256转为整数,超出-256),创建时内容被初始化为0
new Blob(arr,options):返回一个blob对象(可理解为二进制的数据对象),常用用于文件下载
canvas.toBlob(callback, type, quality):创造 Blob 对象,用以展示 canvas 上的图片;这个图片文件可以被缓存或保存到本地
具体参数:(1)callback:回调函数,可获得一个单独的 Blob 对象参数。如果图像未被成功创建,可能会获得 null 值
(2)type:指定图片格式,默认格式(未指定或不支持)为 image/png
(3)quality:值在 0 与 1 之间,当请求图片格式为 image/jpeg 或者 image/webp 时用来指定图片展示质量。如果这个参数的值不在指定类型与范围之内
这里基本就能完成多图片上传的压缩旋转和预览功能,觉得有用的大佬们点赞收藏
更多推荐
所有评论(0)