前言

最近项目需求需要进行多图片或者文件夹拖拽实现图片上传的功能,现在对功能整体逻辑进行介绍:
多图片或者单张图片进行拖拽 =》 图片进行压缩至224分辨率 =》通过AI接口返回图片需要旋转至正向的角度数 =》通过canvas绘制进行旋转操作 =》将canvas绘制的img图片进行toDataURL预览操作 =》将canvas绘制的blob格式的二进制数据和图片的路径传给后端进行保存

整个流程看着比较繁琐,但是图片处理的时间速度还是比较快,接下来直接上代码,文件夹和图片拖拽的代码后续再进行整理,这里直接对图片的file进行处理

多图片的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 时用来指定图片展示质量。如果这个参数的值不在指定类型与范围之内

这里基本就能完成多图片上传的压缩旋转和预览功能,觉得有用的大佬们点赞收藏

Logo

前往低代码交流专区

更多推荐