UNPKG

mcanvas

Version:

the image-composer or image-croper that can draw image/text/watermark or crop the image.

148 lines (135 loc) 4.57 kB
import { Queue } from '@Src/utils/queue' import { getSize, is, extend } from '@Src/utils' import { crop } from '@Src/utils/crop' import { blur, flip, gray, mosaic, oil } from '@Src/utils/filter' import { Canvas } from '@Src/canvas' export class MImage { private _image: TCommon.image private _queue: Queue private _error: (error) => any constructor(image: TCommon.image) { this._image = image this._queue = new Queue() this.clear() } public clear() { this._getImage()._drawCanvas() return this } private _drawCanvas() { return this._run((img) => { const { iw, ih } = getSize(img) const [cvs, ctx] = Canvas.create(iw, ih) ctx.drawImage(img, 0, 0, iw, ih) return { cvs, ctx } }) } private _getImage() { // 加载图片 return this._run(() => ( new Promise(async (resolve) => { if (is.str(this._image)) { Canvas.getImage(this._image) .then(img => resolve(this._image = img)) .catch(this._error) } else { resolve(this._image) } }) )) } private _run(fn: (data: any) => any) { this._queue.push((next, data) => { setTimeout(async () => { const nextData = fn(data) if (is.promise(nextData)) { nextData.then(next) } else { next(nextData) } }, 0) }) return this } public draw(exportConfig: TCommon.drawOptions | ((b64: string) => void) = {}) { return new Promise((resolve, reject) => { let config = { type: 'jpeg', quality: 1, exportType: 'base64', success(result) {}, error(err) {}, } if (is.fn(exportConfig)) { config.success = exportConfig } else { config = extend(true, config, exportConfig) if (config.type === 'jpg') config.type = 'jpeg' } const { exportType, type, quality, success, error } = config const _success = (result) => { success(result) resolve(result) this.clear() } this._error = (err) => { error(err) reject(err) } this._queue.perform(({ cvs, quality: _quailty }) => { if (exportType === 'canvas') { _success(cvs) } else { setTimeout(() => { const b64 = cvs.toDataURL(`image/${type}`, _quailty || quality) _success(b64) }, 0) } }) }) } // 裁剪 public crop(options: TImage.cropOptions = {}) { return this._run(({ cvs }) => crop(cvs, options)) } // 压缩质量,修改尺寸 public compress(options: TImage.compressOptions = {}) { return this._run(({ cvs, ctx }) => { let { quality, width, height } = options const ratio = cvs.width / cvs.height if (!is.num(width) && !is.num(height)) return { cvs, ctx, quality } if (!is.num(width)) width = height! * ratio if (!is.num(height)) height = width / ratio const [nCvs, nCtx] = Canvas.create(width, height) nCtx.drawImage(cvs, 0, 0, width, height) return { cvs: nCvs, ctx: nCtx, quality } }) } // 滤镜 public filter(type: TImage.ftype, ...data) { return this._run(({ cvs, ctx }) => { let fcvs = cvs, fctx = ctx switch (type) { case 'blur': [fcvs, fctx] = blur(cvs, ...data) break case 'flip': [fcvs, fctx] = flip(cvs, ...data) break case 'gray': [fcvs, fctx] = gray(cvs) break case 'mosaic': [fcvs, fctx] = mosaic(cvs, ...data) break case 'oil': [fcvs, fctx] = oil(cvs, ...data) break } return { cvs: fcvs, ctx: fctx, } }) } }