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
text/typescript
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,
}
})
}
}