195 lines
8.9 KiB
JavaScript
195 lines
8.9 KiB
JavaScript
|
import uni from "./utils/global";
|
||
|
import { handleBuildOpts, extendMount } from "./utils/utils";
|
||
|
import { getCanvas2dContext } from "./utils/wx-utils";
|
||
|
// 扩展挂载储存
|
||
|
let drawPosterExtend = {};
|
||
|
let drawCtxPosterExtend = {};
|
||
|
class DrawPoster {
|
||
|
/** 构建器, 构建返回当前实例, 并挂载多个方法 */
|
||
|
constructor(canvas, ctx, canvasId, loading, debugging, loadingText, createText, tips) {
|
||
|
var _a;
|
||
|
this.canvas = canvas;
|
||
|
this.ctx = ctx;
|
||
|
|
||
|
this.canvasId = canvasId;
|
||
|
this.loading = loading;
|
||
|
this.debugging = debugging;
|
||
|
this.loadingText = loadingText;
|
||
|
this.createText = createText;
|
||
|
this.executeOnions = [];
|
||
|
this.stopStatus = false;
|
||
|
/** 提示器, 传入消息与数据 */
|
||
|
this.debuggingLog = (message, data, color = "#3489fd") => {
|
||
|
if (this.debugging) {
|
||
|
if (data) {
|
||
|
console.log(`%c${this.canvasId} -> ${message}`, `color: ${color}`, data);
|
||
|
}
|
||
|
else {
|
||
|
console.log(`%c${this.canvasId} -> ${message}`, `color: ${color}`);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
/** 绘制器, 接收执行器函数, 添加到绘制容器中 */
|
||
|
this.draw = (execute) => {
|
||
|
const length = this.executeOnions.length;
|
||
|
this.executeOnions.push(async () => {
|
||
|
var _a, _b;
|
||
|
try {
|
||
|
this.ctx.save();
|
||
|
await execute(this.ctx);
|
||
|
this.ctx.restore();
|
||
|
return true;
|
||
|
}
|
||
|
catch (error) {
|
||
|
const isOutError = ((_b = (_a = error === null || error === void 0 ? void 0 : error.message) === null || _a === void 0 ? void 0 : _a.search) === null || _b === void 0 ? void 0 : _b.call(_a, `'nodeId' of undefined`)) >= 0;
|
||
|
!isOutError && console.error(`${this.canvasId} -> 绘画栈(${length}),绘制错误:`, error);
|
||
|
return false;
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
/** 等待创建绘画, 成功后清空绘制器容器 */
|
||
|
this.awaitCreate = async () => {
|
||
|
this.debuggingLog('绘制海报中...');
|
||
|
this.loading && uni.showLoading({ title: this.loadingText });
|
||
|
const tips = [];
|
||
|
for (let i = 0; i < this.executeOnions.length; i++) {
|
||
|
const execute = this.executeOnions[i];
|
||
|
tips.push(await execute());
|
||
|
}
|
||
|
this.executeOnions = [];
|
||
|
this.debuggingLog('绘制状况', tips);
|
||
|
// 当前绘制为 type2 绘制
|
||
|
if (this.drawType === 'type2d') {
|
||
|
this.loading && uni.hideLoading();
|
||
|
|
||
|
return tips;
|
||
|
}
|
||
|
// 当前绘制为 context 绘制
|
||
|
return await new Promise((resolve) => {
|
||
|
this.ctx.draw(true, () => {
|
||
|
resolve(tips);
|
||
|
this.loading && uni.hideLoading();
|
||
|
});
|
||
|
});
|
||
|
};
|
||
|
/** 创建canvas本地地址 @returns {string} 本地地址 */
|
||
|
this.createImagePath = async (baseOptions = {}) => {
|
||
|
const { canvas, canvasId, executeOnions, awaitCreate } = this;
|
||
|
executeOnions.length && await awaitCreate();
|
||
|
// 如果当前为停止状态
|
||
|
if (this.stopStatus) {
|
||
|
this.stopStatus = false;
|
||
|
return '---stop createImagePath---';
|
||
|
}
|
||
|
this.loading && uni.showLoading({ title: this.createText });
|
||
|
const options = Object.assign({}, baseOptions);
|
||
|
if (this.drawType === 'context')
|
||
|
options.canvasId = canvasId;
|
||
|
if (this.drawType === 'type2d')
|
||
|
options.canvas = canvas;
|
||
|
|
||
|
console.log(options)
|
||
|
return new Promise((resolve, reject) => {
|
||
|
options.success = (res) => {
|
||
|
resolve(res.tempFilePath);
|
||
|
this.loading && uni.hideLoading();
|
||
|
this.debuggingLog('绘制成功 🎉', res, '#19be6b');
|
||
|
};
|
||
|
options.fail = (err) => {
|
||
|
reject(err);
|
||
|
this.loading && uni.hideLoading();
|
||
|
this.debuggingLog('绘制失败 🌟', err, '#fa3534');
|
||
|
};
|
||
|
uni.canvasToTempFilePath(options);
|
||
|
});
|
||
|
};
|
||
|
/** 停止当前绘画, 调用则停止当前绘画堆栈的绘画 */
|
||
|
this.stop = () => {
|
||
|
this.executeOnions = [];
|
||
|
this.stopStatus = true;
|
||
|
};
|
||
|
if (!canvas || !ctx || !canvasId) {
|
||
|
throw new Error("DrawPoster Error: Use DrawPoster.build(string | ops) to build drawPoster instance objects");
|
||
|
}
|
||
|
// 判断当前绘制类型
|
||
|
ctx.drawType = this.drawType = (ctx.draw) ? 'context' : 'type2d';
|
||
|
// 挂载全局实例, 绘画扩展
|
||
|
extendMount(this.ctx, drawCtxPosterExtend, (extend, target) => {
|
||
|
var _a;
|
||
|
(_a = target === null || target === void 0 ? void 0 : target.init) === null || _a === void 0 ? void 0 : _a.call(target, this.canvas, this.ctx);
|
||
|
return (...args) => extend(this.canvas, this.ctx, ...args);
|
||
|
});
|
||
|
extendMount(this, drawPosterExtend, (extend, target) => {
|
||
|
var _a;
|
||
|
(_a = target === null || target === void 0 ? void 0 : target.init) === null || _a === void 0 ? void 0 : _a.call(target, this);
|
||
|
return (...args) => extend(this, ...args);
|
||
|
});
|
||
|
// 当离开页面时, 自动调用停止绘画
|
||
|
const _this = this;
|
||
|
const pages = getCurrentPages();
|
||
|
const page = pages[pages.length - 1];
|
||
|
// 查询标识, 不存在, 在替换页面卸载回调, 避免产生死循环
|
||
|
if (!((_a = page === null || page === void 0 ? void 0 : page.onUnload) === null || _a === void 0 ? void 0 : _a.identification)) {
|
||
|
page.oldOnUnload = page.onUnload;
|
||
|
page.onUnload = function () {
|
||
|
_this === null || _this === void 0 ? void 0 : _this.stop();
|
||
|
page.oldOnUnload();
|
||
|
};
|
||
|
page.onUnload.identification = true;
|
||
|
}
|
||
|
tips && this.debuggingLog('构建完成', { canvas, ctx, selector: canvasId }, '#19be6b');
|
||
|
}
|
||
|
}
|
||
|
/** 传入挂载配置对象, 添加扩展方法 */
|
||
|
DrawPoster.use = (opts) => {
|
||
|
if (opts.name)
|
||
|
drawPosterExtend[opts.name] = opts;
|
||
|
};
|
||
|
/** 传入挂载配置对象, 添加绘画扩展方法 */
|
||
|
DrawPoster.useCtx = (opts) => {
|
||
|
if (opts.name)
|
||
|
drawCtxPosterExtend[opts.name] = opts;
|
||
|
};
|
||
|
/** 构建绘制海报矩形方法, 传入canvas选择器或配置对象, 返回绘制对象 */
|
||
|
DrawPoster.build = async (options, tips = true) => {
|
||
|
var _a, _b, _c, _d, _e;
|
||
|
const config = handleBuildOpts(options);
|
||
|
// 初始化监测当前页面绘制对象
|
||
|
const pages = getCurrentPages();
|
||
|
const page = pages[pages.length - 1];
|
||
|
const gcanvas = DrawPoster.prototype['gcanvas'];
|
||
|
if (page[config.selector + '__dp']) {
|
||
|
return page[config.selector + '__dp'];
|
||
|
}
|
||
|
if (config.gcanvas) {
|
||
|
if (!gcanvas)
|
||
|
console.error('--- 当前未引入gcanvas扩展, 将自动切换为普通 canvas ---');
|
||
|
else
|
||
|
gcanvas.enable((_b = (_a = config.componentThis) === null || _a === void 0 ? void 0 : _a.$refs) === null || _b === void 0 ? void 0 : _b[config.selector], {
|
||
|
bridge: gcanvas.WeexBridge
|
||
|
});
|
||
|
}
|
||
|
// 获取canvas实例
|
||
|
const canvas = config.gcanvas && gcanvas ?
|
||
|
gcanvas.enable((_d = (_c = config.componentThis) === null || _c === void 0 ? void 0 : _c.$refs) === null || _d === void 0 ? void 0 : _d[config.selector], {
|
||
|
bridge: gcanvas.WeexBridge
|
||
|
}) :
|
||
|
await getCanvas2dContext(config.selector, config.componentThis);
|
||
|
const ctx = (((_e = canvas.getContext) === null || _e === void 0 ? void 0 : _e.call(canvas, "2d")) || uni.createCanvasContext(config.selector, config.componentThis));
|
||
|
const dp = new DrawPoster(canvas, ctx, config.selector, config.loading, config.debugging, config.loadingText, config.createText, tips);
|
||
|
// 储存当前绘制对象
|
||
|
page[config.selector + '__dp'] = dp;
|
||
|
return page[config.selector + '__dp'];
|
||
|
};
|
||
|
/** 构建多个绘制海报矩形方法, 传入选择器或配置对象的数组, 返回多个绘制对象 */
|
||
|
DrawPoster.buildAll = async (optionsAll) => {
|
||
|
const dpsArr = await Promise.all(optionsAll.map(async (options) => {
|
||
|
return await DrawPoster.build(options, false);
|
||
|
}));
|
||
|
const dpsObj = {};
|
||
|
dpsArr.forEach(dp => dpsObj[dp.canvasId] = dp);
|
||
|
console.log("%cdraw-poster 构建完成:", "#E3712A", dpsObj);
|
||
|
return dpsObj;
|
||
|
};
|
||
|
export default DrawPoster;
|