有时候咱们有这样的需要,就是对前端选中的图片进行压缩解决。
这样解决的起因可能是。
- 缩小带宽占用率,提高效率。
- 对图片进行裁剪合乎上传需要。(当初手机拍照分辨率很高,间接拿来用比拟大。)
前端对图片进行压缩次要应用到的API有:
- 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办法
该办法次要是应用Image以及File、FileReader来进行转换,传参如果是file,则应用后者,如果只是url,则间接应用Image。
其中留神FilerReader的用法,在h5的开发中很多中央都会应用到。
/**转换成图片 */async function toImage (params: {file?: File, url?: string}): Promise<HTMLImageElement> { 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<File> { 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
办法。
参考:
- <<How to resize image in Javascript?>>