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;