h5中使用javascript在客户端对图片进行压缩和尺寸处理,附ts代码
有时候我们有这样的需求,就是对前端选中的图片进行压缩处理。
这样处理的原因可能是。
- 减少带宽占用率,提高效率。
- 对图片进行裁剪符合上传需求。(现在手机拍照分辨率很高,直接拿来用比较大。)
- Canvas
- Image
- File
- Blob
- FileReader
文章图片
如图,设置三个方法
- toImage
- toCanvas
- toFile
/**主要方法*/
async function miniImage(params:{
url?:string,
file?:File,
quality?:number,
fileName?:string,
size?:{width:number,height:number},
fitLength?:number
}={quality:1,fileName:'压缩图片'}
){
console.assert(params.url||params.file,'url和file必填其一')
console.assert(params.quality<=1&¶ms.quality>0,'quality的取值范围是0-1')
const img = await toImage({file:params.file,url:params.url})
const canvas = toCanvas({img,size:params.size,fitLength:params.fitLength})
return await toFile(canvas,{quality:params.quality,fileName:params.fileName})
}
toImage方法 【h5中使用javascript在客户端对图片进行压缩和尺寸处理,附ts代码】该方法主要是使用Image以及File、FileReader来进行转换,传参如果是file,则使用后者,如果只是url,则直接使用Image。
其中注意FilerReader的用法,在h5的开发中很多地方都会使用到。
/**转换成图片 */
async function toImage (params: {file?: File, url?: string}): Promise {
return new Promise((reso, rej) => {const {file, url} = params
const img = new Image()
img.onload = () => {
return reso(img)
}
// 文件方式
if (file) {
const reader = new FileReader()
reader.onload = (e) => {
img.setAttribute('src', e.target?.result as string)
}
reader.readAsDataURL(file)
} else if (url) {
img.setAttribute('src', url)
} else {
console.error(`解析图片出错`)
}
})
}
toCanvas方法 该方法主要是使用CanvasRenderingContext2D的drawImage方法。
该方法的入参定义:
drawImage(HTMLImageElement,dx,dy,dw,dh)
即传入方法,然后绘制图片,控制绘制位置,以及绘制的宽高。
此外我们还需要做更多的兼容,增加入参,控制图片的尺寸。代码如下。
/**转换成canvas */
function toCanvas (img: HTMLImageElement, options?: {size?: {width: number, height: number}, maxLength?: number}) {
const canvas = document.createElement('canvas')
let {size, maxLength} = options ?? {}
let {height, width} = img
if (size || maxLength) {
if ((!size?.height || !size.width) && !maxLength) maxLength = size?.height ?? size?.width
// 设置长度并去适应
if (maxLength) {
let maxlen = Math.max(height, width)
let rate = maxLength / maxlen
height = maxlen === height ? maxLength : height * rate
width = maxlen === width ? maxLength : width * rate
} else if (size) {
// 设置了尺寸
height = size.height
width = size.width
}
}
canvas.height = height
canvas.width = width
const ctv = canvas.getContext('2d')
ctv?.drawImage(img, 0, 0, width, height)
return canvas
}
toFile 方法 最后一步,把图片转成我们需要的文件用以上传。
该步骤主要是使用canvas的toBlob方法,然后通过File来生成新的file。
注:在js中,一个文件基本就是Blob加上name。
具体代码如下:
/**canvas转文件 */
function canvasToFile (canvas: HTMLCanvasElement, options: {fileName?: string, quality?: number} = {quality: 1, fileName: '图片'}): Promise {
return new Promise((reso, rej) => {
canvas.toBlob((blob) => {
const file = new File([ blob as Blob ], options!.fileName as string, {
type: 'image/png',
})
reso(file)
}, '', options.quality)
})
}
miniImageByUrl方法 最后我们结合上面在写一个方法用来预览,把生成的canvas直接转成dataUrl,在页面展示。
/**处理图片压缩,并且转成url */
export const imageMinByUrl = async (
params: {
file?: File
url?: string
quality?: number
maxLength?: number,
size?: {height: number, width: number},
} = {quality: 1}
) => {
console.assert(params.file || params.url, '必须存在file或者url入参')
const img = await toImage({file: params.file, url: params.url})
const canvas = toCanvas(img, {size: params.size, maxLength: params.maxLength})
return canvas.toDataURL('image/png', params.quality)
}
npm中可以通过cdd-lib直接使用,该库提供了
imageMinByUrl
和imageMin
方法。参考:
- <>
推荐阅读
- 人脸识别|yolo-face 使用yolo v2 在CelebA上训练的人脸检测器
- 投稿|LNG,全球危机中最赚钱的生意
- 奇妙之旅-GIS|如何在QGIS中将纬度和经度添加为CSV文件
- 奇妙之旅-GIS|GIS 在地质学中的10个重要性
- 技术分享成就现在的我(中间件兴趣圈荣获CSDN2020博客之星亚军)
- 投稿|从十年第一到卖身求生,又要砸下千亿,他可能是中国汽车业最坎坷的老板了
- 新消费|【招募】DTC出海成长俱乐部线下闭门会,招募品牌决策者,呼唤中国品牌全球化同行人丨钛媒体新消费
- GO语言集成开发工具环境(GoLand 2022激活中文)
- 如何使用流程|如何使用流程 中的 DataObject 并为流程设置租户
- python|使用 Python 实现一个简单的智能聊天机器人