赞
踩
我们前面已有多篇文章介绍了前端文件和图像操作相关的知识,这些博文对我们如何处理图像文件,提供了一些基础和原理性的知识,能够帮助我们更了解所需要使用到的图片文件和相应对象处理。
本文将在之前的基础上,提炼出前端图像文件操作中存在的各个对象之间的转换方法,这将有利于我们更加深入的理解图像知识,并且方便在实际项目中直接使用对应的方法。
当前我们在前端JS中处理图像时,大致有四种不同的图像数据类型:
<img>
对应的对象和类型,用于加载图像资源<canvas>
对应的对象和类型,用于加载图像资源和操作图像数据各个API对象与相应的知识,可见以下博文,
Blob、Object-URL等内容, 前端二进制处理相关的(如Blob、File、Object-URL)。
文件上传读取的方式, web前端文件上传可选择的4种方式。
Base64相关的知识(Data-URL), Base64编解码知识详解(Data-URL)。
Dom对象相关的API接口, 前端图片处理API总结(如Image、ImageData)。
前端需要了解的图片基础知识, 图片基础介绍与前端支持的格式。
下面我们从前端图像加载的数据类型上,介绍各自类型之间一一对应的转换方法,其中有些类型之间可以直接转换,有些则需要使用第三方类型进行间接转换。
使用Web-API对象,可以直接将上传的File(Blob)对象转换成URL类型的,主要是Data-URL(Base64图像字符串)和Object-URL。
这个过程需要使用到 FileReader
文件读取对象,通过 readAsDataURL()
方法将读取到的文件内容转换成Base64字符串,以 Data-URL
的格式输出。
由于FileReader对象实例,是异步加载文件内容,所以我们通过 Promise
的方式返回:
function file2DataURL(file) {
return new Promise(resolve => {
const reader = new FileReader()
reader.onload = () => {
resolve(reader.result)
}
reader.readAsDataURL(file)
})
}
将File对象转为 Object-URL
,则直接使用 URL.createObjectURL()
就可以转换了:
function file2ObjectURL(file) {
const url = URL.createObjectURL(file)
return url
}
注意,我们需要手动释放
Object-URL
,通过URL.revokeObjectURL(url)
方法。
加载图像的URL资源数据后,转换成Image对象。
Image对象能够加载四种类型的图像资源:本地路径、网络地址、Data-URL 和 Object-URL。他们的加载方式都是一样的,也同样是异步加载:
function url2Image(url) {
return new Promise(resolve => {
const image = new Image()
image.onload = () => {
resolve(image)
}
image.src = url
})
}
在服务接口请求中,我们可以将url转换成blob对象,使用 XHR
或 fetch
都可以达成目标:
async function url2Blob (url) {
return await (await fetch(url)).blob()
}
主要将Image直接绘制到Canvas中。
Image实例作为HTMLImageElement对象类型,可以被直接绘制到canvas中,转换也很容易:
function image2Canvas(image) {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = image.width
canvas.height = image.height
ctx.drawImage(image, 0, 0)
return canvas
}
toDataURL()方法可以把Canvas转换成Data-URL:
function canvas2DataURL(canvas) {
return canvas.toDataURL()
}
语法:
canvas.toDataURL(mimeType, quality)
参数:
- mimeType:可选,图像的mimeType类型。默认值是
image/png
。- quality:可选,表示图像质量,范围
0-1
,默认0.92,对jpg和webp有效。对png格式无效。
要把Canvas转化成Blob,可以直接使用Canvas的方法 toBlob()
。
这里得到的Blob可以直接当做File来使用,使用 FileReader
或 URL.createObjectURL()
进行处理:
function canvas2Blob(canvas) {
return new Promise(resolve => {
canvas.toBlob((blob) => {
resolve(blob)
})
})
}
语法:
void canvas.toBlob(callback, mimeType, quality)
参数:
- callback:成功后的回调函数
- mimeType:可选,图像的mimeType类型。默认值是
image/png
。- quality:可选,表示图像质量,范围
0-1
,默认0.92,对jpg和webp有效。对png格式无效。
以上的方法,都是在几个对象之间进行单个API的直接转换,下面则是需要进行多个方法的组合,使用第三个对象中转,才能正确转换。
从上文可知,File对象可以直接转换成 Data-URL 或 Object-URL,这样就能中转成Image:
方案一,先转成Object-URL,再加载Image:
async function file2Image(file) {
const objUrl = file2ObjectURL(file)
const img = await url2Image(objUrl)
URL.revokeObjectURL(objUrl)
return img
}
方案二,先转成Data-URL,再加载Image::
async function file2Image(file) {
const dataUrl = await file2DataURL(file)
const img = await url2Image(dataUrl)
return img
}
方案一,createImageBitmap()
方法可以读取File对象,并返回Canvas能够接收的图像对象 ImageBitmap
,并写入到canvas中:
async function file2Canvas(file) {
const imageBitmap = await createImageBitmap(file)
const canvas = document.createElement('canvas')
canvas.width = imageBitmap.width
canvas.height = imageBitmap.height
const ctx = canvas.getContext('2d')
ctx.drawImage(imageBitmap, 0, 0)
return canvas
}
ImageBitmap
表示位图图像,拥有宽高属性,能够被绘制到Canvas中。
drawImage()
可以接收 HTMLImageElement、ImageBitmap等对象作为数据源,绘制到画布中。
方案二,使用Image中转:
async function file2Canvas(file) {
const img = await file2Image(file)
const canvas = image2Canvas(img)
return canvas
}
Canvas有了 toDataURL()
和 toBlob()
方法,要转换成Image就非常方便了,结合以上已有的方法。
方案一,通过Blob中转:
async function canvas2Image(canvas) {
const blob = await canvas2Blob(canvas)
const img = await file2Image(blob)
return img
}
方案二,通过Data-URL中转:
async function canvas2Image(canvas) {
const dataUrl = canvas2DataURL(canvas)
const img = await url2Image(dataUrl)
return img
}
方案一,直接解析Base64字符串数据,进行转换:
function dataURL2Blob(dataUrl) {
const bsArr = dataUrl.split(',')
const pattern = /^data:(.*?)(;base64)/
const type = bsArr[0].match(pattern)[1]
const dataStr = atob(bsArr[1])
const len = dataStr.length
const uint8Array = new Uint8Array(len)
for (let i = 0; i < len; i++) {
uint8Array[i] = dataStr.charCodeAt(i)
}
return new Blob([uint8Array], { type })
}
方案二,通过多个方法进行中转:
async function dataURL2Blob(dataUrl) {
const img = await url2Image(dataUrl)
const canvas = image2Canvas(img)
const blob = await canvas2Blob(canvas)
return blob
}
方案二里也有DataURL到Canvas的转换。
我们在前端开发中,常用的转换一般是在 File、Image、Canvas 等几个主要对象之间展开,通过不同的形式加载不同的图像资源,有助于我们展示图片或者处理图像数据。
以上给出的方法,都是可以直接使用的,在我们操作这些对象时,根据需求调用即可。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。