index.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import { isObject } from 'lodash';
  2. import { queryFields, UNI_PLATFORM } from '../utils';
  3. import { DebuggingLog } from './debugginglog';
  4. import { Plugins, globalUse } from './plugin';
  5. async function useDrawPoster(...args) {
  6. const $options = (() => {
  7. const _default = {
  8. selector: '',
  9. componentThis: undefined,
  10. type: UNI_PLATFORM === 'mp-weixin' ? '2d' : 'context',
  11. loading: false,
  12. debug: false,
  13. gcanvas: false
  14. };
  15. let _overrides;
  16. if (isObject(args[0])) {
  17. _overrides = args[0];
  18. }
  19. else if (isObject(args[1])) {
  20. _overrides = args[1];
  21. _overrides.selector = args[0];
  22. }
  23. else {
  24. _overrides = { selector: args[0] };
  25. }
  26. const options = { ..._default, ..._overrides };
  27. options.selector = options.selector.replace('#', '');
  28. if (options.type === '2d') {
  29. options.selector = `#${options.selector}`;
  30. }
  31. if (options.loading === true) {
  32. options.loading = { render: '绘制海报中...', create: '生成图片中...' };
  33. }
  34. if (isObject(options.loading)) {
  35. options.loading.render = options.loading?.render ?? '绘制海报中...';
  36. options.loading.create = options.loading?.create ?? '生成图片中...';
  37. }
  38. if (!UNI_PLATFORM) {
  39. console.warn('注意! draw-poster未开启uni条件编译! 当环境是微信小程序将不会动态切换为type=2d模式');
  40. console.warn(`请在vue.config.js中的'transpileDependencies'中添加 'u-draw-poster' `);
  41. }
  42. return options;
  43. })();
  44. const pages = getCurrentPages();
  45. const page = pages[pages.length - 1];
  46. const dp = { $options };
  47. const ps = new Plugins(dp);
  48. const consola = new DebuggingLog(dp);
  49. let stacks = [];
  50. let isStop = false;
  51. const build = async () => {
  52. if (dp.$drawPrototype)
  53. return dp.$drawPrototype;
  54. const _nodeInfo = await queryFields($options.selector, $options.componentThis, {
  55. node: true
  56. });
  57. const canvas = _nodeInfo?.node || {};
  58. const ctx = canvas.getContext?.('2d') ||
  59. uni.createCanvasContext($options.selector, $options.componentThis);
  60. if (!canvas || !ctx || !$options.selector) {
  61. throw new Error('DrawPoster Error: useDrawPoster to build drawPoster instance');
  62. }
  63. return { canvas, ctx };
  64. };
  65. const render = async () => {
  66. if ($options.loading)
  67. uni.showLoading({ title: $options.loading.render });
  68. consola.log('绘制海报中...');
  69. const tips = [];
  70. for (const next of stacks) {
  71. tips.push(await next());
  72. }
  73. stacks = [];
  74. consola.log('绘制状况: ', undefined, tips);
  75. if ($options.type === 'context') {
  76. await new Promise((resolve) => {
  77. dp.ctx.draw(true, resolve);
  78. });
  79. }
  80. if ($options.loading)
  81. uni.hideLoading();
  82. return tips;
  83. };
  84. const createImagePath = async (_options_ = {}) => {
  85. if (stacks.length > 0)
  86. await dp.render();
  87. if (isStop) {
  88. isStop = false;
  89. return Promise.reject();
  90. }
  91. if ($options.loading)
  92. uni.showLoading({ title: $options.loading.create });
  93. const options = _options_;
  94. if ($options.type === '2d') {
  95. ;
  96. options.canvas = dp.canvas;
  97. }
  98. if ($options.type === 'context') {
  99. ;
  100. options.canvasId = dp.id;
  101. }
  102. return new Promise((resolve, reject) => {
  103. options.success = (res) => {
  104. resolve(res.tempFilePath);
  105. $options.loading && uni.hideLoading();
  106. consola.success('绘制成功', res);
  107. };
  108. options.fail = (err) => {
  109. reject(err);
  110. $options.loading && uni.hideLoading();
  111. consola.success('绘制失败', err);
  112. };
  113. uni.canvasToTempFilePath(options);
  114. });
  115. };
  116. const draw = async (func) => {
  117. const length = stacks.length;
  118. stacks.push(async () => {
  119. try {
  120. dp.ctx.save();
  121. await func(dp.ctx);
  122. dp.ctx.restore();
  123. return true;
  124. }
  125. catch (error) {
  126. if (!error?.message?.includes?.(`'nodeId' of undefined`))
  127. consola.error(`绘画栈(${length}),绘制错误:`, error);
  128. return false;
  129. }
  130. });
  131. };
  132. const stop = () => {
  133. stacks = [];
  134. isStop = true;
  135. };
  136. if (page[`__dp_${dp.id}`])
  137. return page[`__dp_${dp.id}`];
  138. Object.defineProperty(dp, 'id', { get: () => $options.selector });
  139. Object.defineProperty(dp, 'plugins', { get: () => ps.plugins });
  140. ps.run('beforeMount');
  141. const { canvas, ctx } = await build();
  142. Object.defineProperty(dp, 'canvas', { get: () => canvas });
  143. Object.defineProperty(dp, 'ctx', { get: () => ctx });
  144. Object.defineProperty(dp, 'render', { get: () => render });
  145. Object.defineProperty(dp, 'createImagePath', { get: () => createImagePath });
  146. Object.defineProperty(dp, 'draw', { get: () => draw });
  147. Object.defineProperty(dp, 'stop', { get: () => stop });
  148. Object.defineProperty(dp, 'use', { get: () => ps.use });
  149. dp.canvas.width = $options.width ?? 0;
  150. dp.canvas.height = $options.height ?? 0;
  151. ps.run('mounted');
  152. $options.debug && consola.success('构建成功!', dp);
  153. page[`__dp_${dp.id}`] = dp;
  154. const _onUnload = page.onUnload;
  155. page.onUnload = function () {
  156. ps.run('beforeUnmount');
  157. dp.stop();
  158. _onUnload();
  159. ps.run('unmounted');
  160. };
  161. return dp;
  162. }
  163. useDrawPoster.use = globalUse;
  164. export { useDrawPoster };
  165. //# sourceMappingURL=index.js.map