@leafer-draw/miniapp 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { LeaferCanvasBase, Platform, canvasPatch, DataHelper, canvasSizeAttrs, ResizeEvent, Creator, LeaferImage, FileHelper, LeafList, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, Bounds, LeafBoundsHelper, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, AnimateEvent, BoundsHelper, MatrixHelper, AlignHelper, ImageEvent, AroundHelper, PointHelper, Direction4, TwoPointBoundsHelper, TaskProcessor, Matrix } from '@leafer/core';
1
+ import { LeaferCanvasBase, Platform, canvasPatch, DataHelper, canvasSizeAttrs, ResizeEvent, Creator, LeaferImage, defineKey, FileHelper, LeafList, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, Bounds, LeafBoundsHelper, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, AnimateEvent, BoundsHelper, MatrixHelper, MathHelper, AlignHelper, ImageEvent, AroundHelper, PointHelper, Direction4, TwoPointBoundsHelper, TaskProcessor, Matrix } from '@leafer/core';
2
2
  export * from '@leafer/core';
3
3
  export { LeaferImage } from '@leafer/core';
4
4
  import { PaintImage, ColorConvert, PaintGradient, Export, Group, TextConvert, Paint, Effect } from '@leafer-ui/draw';
@@ -7,7 +7,8 @@ export * from '@leafer-ui/draw';
7
7
  class LeaferCanvas extends LeaferCanvasBase {
8
8
  get allowBackgroundColor() { return false; }
9
9
  init() {
10
- let { view } = this.config;
10
+ const { config } = this;
11
+ let view = config.view || config.canvas;
11
12
  if (view) {
12
13
  if (typeof view === 'string') {
13
14
  if (view[0] !== '#')
@@ -37,16 +38,20 @@ class LeaferCanvas extends LeaferCanvasBase {
37
38
  else {
38
39
  this.view = view.view || view;
39
40
  }
40
- this.__createContext();
41
+ this.view.getContext ? this.__createContext() : this.unrealCanvas();
41
42
  const { width, height, pixelRatio } = this.config;
42
43
  const size = { width: width || view.width, height: height || view.height, pixelRatio };
43
44
  this.resize(size);
44
- if (this.context.roundRect) {
45
- this.roundRect = function (x, y, width, height, radius) {
46
- this.context.roundRect(x, y, width, height, typeof radius === 'number' ? [radius] : radius);
47
- };
45
+ if (this.context) {
46
+ if (this.viewSelect)
47
+ Platform.renderCanvas = this;
48
+ if (this.context.roundRect) {
49
+ this.roundRect = function (x, y, width, height, radius) {
50
+ this.context.roundRect(x, y, width, height, typeof radius === 'number' ? [radius] : radius);
51
+ };
52
+ }
53
+ canvasPatch(this.context.__proto__);
48
54
  }
49
- canvasPatch(this.context.__proto__);
50
55
  }
51
56
  __createView() {
52
57
  this.view = Platform.origin.createCanvas(1, 1);
@@ -64,10 +69,12 @@ class LeaferCanvas extends LeaferCanvasBase {
64
69
  callback();
65
70
  });
66
71
  }
67
- startAutoLayout(_autoBounds, listener) {
72
+ startAutoLayout(autoBounds, listener) {
68
73
  this.resizeListener = listener;
69
- this.checkSize = this.checkSize.bind(this);
70
- Platform.miniapp.onWindowResize(this.checkSize);
74
+ if (autoBounds) {
75
+ this.checkSize = this.checkSize.bind(this);
76
+ Platform.miniapp.onWindowResize(this.checkSize);
77
+ }
71
78
  }
72
79
  checkSize() {
73
80
  if (this.viewSelect) {
@@ -76,13 +83,8 @@ class LeaferCanvas extends LeaferCanvasBase {
76
83
  const { width, height } = this.clientBounds;
77
84
  const { pixelRatio } = this;
78
85
  const size = { width, height, pixelRatio };
79
- if (!this.isSameSize(size)) {
80
- const oldSize = {};
81
- DataHelper.copyAttrs(oldSize, this, canvasSizeAttrs);
82
- this.resize(size);
83
- if (this.width !== undefined)
84
- this.resizeListener(new ResizeEvent(size, oldSize));
85
- }
86
+ if (!this.isSameSize(size))
87
+ this.emitResize(size);
86
88
  });
87
89
  }, 500);
88
90
  }
@@ -92,6 +94,16 @@ class LeaferCanvas extends LeaferCanvasBase {
92
94
  this.resizeListener = null;
93
95
  Platform.miniapp.offWindowResize(this.checkSize);
94
96
  }
97
+ unrealCanvas() {
98
+ this.unreal = true;
99
+ }
100
+ emitResize(size) {
101
+ const oldSize = {};
102
+ DataHelper.copyAttrs(oldSize, this, canvasSizeAttrs);
103
+ this.resize(size);
104
+ if (this.width !== undefined)
105
+ this.resizeListener(new ResizeEvent(size, oldSize));
106
+ }
95
107
  }
96
108
 
97
109
  const { mineType, fileType } = FileHelper;
@@ -100,120 +112,121 @@ Object.assign(Creator, {
100
112
  image: (options) => new LeaferImage(options)
101
113
  });
102
114
  function useCanvas(_canvasType, app) {
103
- if (!Platform.origin) {
104
- Platform.origin = {
105
- createCanvas: (width, height, _format) => app.createOffscreenCanvas({ type: '2d', width, height }),
106
- canvasToDataURL: (canvas, type, quality) => canvas.toDataURL(mineType(type), quality),
107
- canvasToBolb: (canvas, type, quality) => canvas.toBuffer(type, { quality }),
108
- canvasSaveAs: (canvas, filePath, quality) => {
109
- let data = canvas.toDataURL(mineType(fileType(filePath)), quality);
110
- data = data.substring(data.indexOf('64,') + 3);
111
- return Platform.origin.download(data, filePath);
112
- },
113
- download(data, filePath) {
114
- return new Promise((resolve, reject) => {
115
- let toAlbum;
116
- if (!filePath.includes('/')) {
117
- filePath = `${app.env.USER_DATA_PATH}/` + filePath;
118
- toAlbum = true;
119
- }
120
- const fs = app.getFileSystemManager();
121
- fs.writeFile({
122
- filePath,
123
- data,
124
- encoding: 'base64',
125
- success() {
126
- if (toAlbum) {
127
- Platform.miniapp.saveToAlbum(filePath).then(() => {
128
- fs.unlink({ filePath });
129
- resolve();
130
- });
131
- }
132
- else {
115
+ Platform.origin = {
116
+ createCanvas: (width, height, _format) => app.createOffscreenCanvas({ type: '2d', width, height }),
117
+ canvasToDataURL: (canvas, type, quality) => canvas.toDataURL(mineType(type), quality),
118
+ canvasToBolb: (canvas, type, quality) => canvas.toBuffer(type, { quality }),
119
+ canvasSaveAs: (canvas, filePath, quality) => {
120
+ let data = canvas.toDataURL(mineType(fileType(filePath)), quality);
121
+ data = data.substring(data.indexOf('64,') + 3);
122
+ return Platform.origin.download(data, filePath);
123
+ },
124
+ download(data, filePath) {
125
+ return new Promise((resolve, reject) => {
126
+ let toAlbum;
127
+ if (!filePath.includes('/')) {
128
+ filePath = `${app.env.USER_DATA_PATH}/` + filePath;
129
+ toAlbum = true;
130
+ }
131
+ const fs = app.getFileSystemManager();
132
+ fs.writeFile({
133
+ filePath,
134
+ data,
135
+ encoding: 'base64',
136
+ success() {
137
+ if (toAlbum) {
138
+ Platform.miniapp.saveToAlbum(filePath).then(() => {
139
+ fs.unlink({ filePath });
133
140
  resolve();
134
- }
135
- },
136
- fail(error) {
137
- reject(error);
141
+ });
138
142
  }
139
- });
140
- });
141
- },
142
- loadImage(src) {
143
- return new Promise((resolve, reject) => {
144
- const img = Platform.canvas.view.createImage();
145
- img.onload = () => { resolve(img); };
146
- img.onerror = (error) => { reject(error); };
147
- img.src = Platform.image.getRealURL(src);
143
+ else {
144
+ resolve();
145
+ }
146
+ },
147
+ fail(error) {
148
+ reject(error);
149
+ }
148
150
  });
149
- },
150
- noRepeat: 'repeat-x'
151
- };
152
- Platform.miniapp = {
153
- select(name) {
154
- return app.createSelectorQuery().select(name);
155
- },
156
- getBounds(select) {
157
- return new Promise((resolve) => {
158
- select.boundingClientRect().exec((res) => {
159
- const rect = res[1];
160
- resolve({ x: rect.top, y: rect.left, width: rect.width, height: rect.height });
161
- });
151
+ });
152
+ },
153
+ loadImage(src) {
154
+ return new Promise((resolve, reject) => {
155
+ const img = Platform.canvas.view.createImage();
156
+ img.onload = () => { resolve(img); };
157
+ img.onerror = (error) => { reject(error); };
158
+ img.src = Platform.image.getRealURL(src);
159
+ });
160
+ },
161
+ noRepeat: 'repeat-x'
162
+ };
163
+ Platform.miniapp = {
164
+ select(name) {
165
+ return app.createSelectorQuery().select(name);
166
+ },
167
+ getBounds(select) {
168
+ return new Promise((resolve) => {
169
+ select.boundingClientRect().exec((res) => {
170
+ const rect = res[1];
171
+ resolve({ x: rect.top, y: rect.left, width: rect.width, height: rect.height });
162
172
  });
163
- },
164
- getSizeView(select) {
165
- return new Promise((resolve) => {
166
- select.fields({ node: true, size: true }).exec((res) => {
167
- const data = res[0];
168
- resolve({ view: data.node, width: data.width, height: data.height });
169
- });
173
+ });
174
+ },
175
+ getSizeView(select) {
176
+ return new Promise((resolve) => {
177
+ select.fields({ node: true, size: true }).exec((res) => {
178
+ const data = res[0];
179
+ resolve({ view: data.node, width: data.width, height: data.height });
170
180
  });
171
- },
172
- saveToAlbum(path) {
173
- return new Promise((resolve) => {
174
- app.getSetting({
175
- success: (res) => {
176
- if (res.authSetting['scope.writePhotosAlbum']) {
177
- app.saveImageToPhotosAlbum({
178
- filePath: path,
179
- success() { resolve(true); }
180
- });
181
- }
182
- else {
183
- app.authorize({
184
- scope: 'scope.writePhotosAlbum',
185
- success: () => {
186
- app.saveImageToPhotosAlbum({
187
- filePath: path,
188
- success() { resolve(true); }
189
- });
190
- },
191
- fail: () => { }
192
- });
193
- }
181
+ });
182
+ },
183
+ saveToAlbum(path) {
184
+ return new Promise((resolve) => {
185
+ app.getSetting({
186
+ success: (res) => {
187
+ if (res.authSetting['scope.writePhotosAlbum']) {
188
+ app.saveImageToPhotosAlbum({
189
+ filePath: path,
190
+ success() { resolve(true); }
191
+ });
194
192
  }
195
- });
193
+ else {
194
+ app.authorize({
195
+ scope: 'scope.writePhotosAlbum',
196
+ success: () => {
197
+ app.saveImageToPhotosAlbum({
198
+ filePath: path,
199
+ success() { resolve(true); }
200
+ });
201
+ },
202
+ fail: () => { }
203
+ });
204
+ }
205
+ }
196
206
  });
197
- },
198
- onWindowResize(fun) {
199
- app.onWindowResize(fun);
200
- },
201
- offWindowResize(fun) {
202
- app.offWindowResize(fun);
203
- }
204
- };
205
- Platform.event = {
206
- stopDefault(_origin) { },
207
- stopNow(_origin) { },
208
- stop(_origin) { }
209
- };
210
- Platform.canvas = Creator.canvas();
211
- Platform.conicGradientSupport = !!Platform.canvas.context.createConicGradient;
212
- }
207
+ });
208
+ },
209
+ onWindowResize(fun) {
210
+ app.onWindowResize(fun);
211
+ },
212
+ offWindowResize(fun) {
213
+ app.offWindowResize(fun);
214
+ }
215
+ };
216
+ Platform.event = {
217
+ stopDefault(_origin) { },
218
+ stopNow(_origin) { },
219
+ stop(_origin) { }
220
+ };
221
+ Platform.canvas = Creator.canvas();
222
+ Platform.conicGradientSupport = !!Platform.canvas.context.createConicGradient;
213
223
  }
214
224
  Platform.name = 'miniapp';
215
- Platform.requestRender = function (render) { Platform.canvas.view.requestAnimationFrame(render); };
216
- Platform.devicePixelRatio = wx.getSystemInfoSync().pixelRatio;
225
+ Platform.requestRender = function (render) {
226
+ const { view } = (Platform.renderCanvas || Platform.canvas);
227
+ view.requestAnimationFrame ? view.requestAnimationFrame(render) : setTimeout(render, 16);
228
+ };
229
+ defineKey(Platform, 'devicePixelRatio', { get() { return Math.max(1, wx.getSystemInfoSync().pixelRatio); } });
217
230
 
218
231
  class Watcher {
219
232
  get childrenChanged() { return this.hasAdd || this.hasRemove || this.hasVisible; }
@@ -691,14 +704,14 @@ class Renderer {
691
704
  if (Debug.showRepaint)
692
705
  this.canvas.strokeWorld(bounds, 'red');
693
706
  this.target.__render(this.canvas, options);
694
- this.renderBounds = realBounds || bounds;
707
+ this.renderBounds = realBounds = realBounds || bounds;
695
708
  this.renderOptions = options;
696
- this.totalBounds.isEmpty() ? this.totalBounds = this.renderBounds : this.totalBounds.add(this.renderBounds);
709
+ this.totalBounds.isEmpty() ? this.totalBounds = realBounds : this.totalBounds.add(realBounds);
697
710
  if (Debug.showHitView)
698
711
  this.renderHitView(options);
699
712
  if (Debug.showBoundsView)
700
713
  this.renderBoundsView(options);
701
- this.canvas.updateRender();
714
+ this.canvas.updateRender(realBounds);
702
715
  }
703
716
  renderHitView(_options) { }
704
717
  renderBoundsView(_options) { }
@@ -1146,10 +1159,13 @@ function repeatMode(data, box, width, height, x, y, scaleX, scaleY, rotation, al
1146
1159
  const { get: get$2, translate } = MatrixHelper;
1147
1160
  const tempBox = new Bounds();
1148
1161
  const tempPoint = {};
1162
+ const tempScaleData = {};
1149
1163
  function createData(leafPaint, image, paint, box) {
1150
- const { blendMode } = paint;
1164
+ const { blendMode, sync } = paint;
1151
1165
  if (blendMode)
1152
1166
  leafPaint.blendMode = blendMode;
1167
+ if (sync)
1168
+ leafPaint.sync = sync;
1153
1169
  leafPaint.data = getPatternData(paint, box, image);
1154
1170
  }
1155
1171
  function getPatternData(paint, box, image) {
@@ -1169,13 +1185,10 @@ function getPatternData(paint, box, image) {
1169
1185
  x += (box.width - width * scaleX) / 2, y += (box.height - height * scaleY) / 2;
1170
1186
  }
1171
1187
  }
1172
- else if (size) {
1173
- scaleX = (typeof size === 'number' ? size : size.width) / width;
1174
- scaleY = (typeof size === 'number' ? size : size.height) / height;
1175
- }
1176
- else if (scale) {
1177
- scaleX = typeof scale === 'number' ? scale : scale.x;
1178
- scaleY = typeof scale === 'number' ? scale : scale.y;
1188
+ else if (scale || size) {
1189
+ MathHelper.getScaleData(scale, size, image, tempScaleData);
1190
+ scaleX = tempScaleData.scaleX;
1191
+ scaleY = tempScaleData.scaleY;
1179
1192
  }
1180
1193
  if (align) {
1181
1194
  const imageBounds = { x, y, width: swapWidth, height: swapHeight };
@@ -1412,7 +1425,7 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
1412
1425
  const { abs } = Math;
1413
1426
  function checkImage(ui, canvas, paint, allowPaint) {
1414
1427
  const { scaleX, scaleY } = ImageManager.patternLocked ? ui.__world : ui.__nowWorld;
1415
- if (!paint.data || paint.patternId === scaleX + '-' + scaleY) {
1428
+ if (!paint.data || (paint.patternId === scaleX + '-' + scaleY && !Export.running)) {
1416
1429
  return false;
1417
1430
  }
1418
1431
  else {
@@ -1446,7 +1459,7 @@ function checkImage(ui, canvas, paint, allowPaint) {
1446
1459
  return true;
1447
1460
  }
1448
1461
  else {
1449
- if (!paint.style || Export.running) {
1462
+ if (!paint.style || paint.sync || Export.running) {
1450
1463
  createPattern(ui, paint, canvas.pixelRatio);
1451
1464
  }
1452
1465
  else {
@@ -2316,6 +2329,7 @@ const ExportModule = {
2316
2329
  export(leaf, filename, options) {
2317
2330
  this.running = true;
2318
2331
  const fileType = FileHelper.fileType(filename);
2332
+ const isDownload = filename.includes('.');
2319
2333
  options = FileHelper.getExportOptions(options);
2320
2334
  return addTask((success) => new Promise((resolve) => {
2321
2335
  const over = (result) => {
@@ -2325,19 +2339,13 @@ const ExportModule = {
2325
2339
  };
2326
2340
  const { toURL } = Platform;
2327
2341
  const { download } = Platform.origin;
2328
- if (filename === 'json') {
2329
- return over({ data: leaf.toJSON(options.json) });
2330
- }
2331
- else if (fileType === 'json') {
2332
- download(toURL(JSON.stringify(leaf.toJSON(options.json)), 'text'), filename);
2333
- return over({ data: true });
2334
- }
2335
- if (filename === 'svg') {
2336
- return over({ data: leaf.toSVG() });
2342
+ if (fileType === 'json') {
2343
+ isDownload && download(toURL(JSON.stringify(leaf.toJSON(options.json)), 'text'), filename);
2344
+ return over({ data: isDownload ? true : leaf.toJSON(options.json) });
2337
2345
  }
2338
- else if (fileType === 'svg') {
2339
- download(toURL(leaf.toSVG(), 'svg'), filename);
2340
- return over({ data: true });
2346
+ if (fileType === 'svg') {
2347
+ isDownload && download(toURL(leaf.toSVG(), 'svg'), filename);
2348
+ return over({ data: isDownload ? true : leaf.toSVG() });
2341
2349
  }
2342
2350
  const { leafer } = leaf;
2343
2351
  if (leafer) {
@@ -2346,14 +2354,8 @@ const ExportModule = {
2346
2354
  let renderBounds, trimBounds, scaleX = 1, scaleY = 1;
2347
2355
  const { worldTransform, isLeafer, isFrame } = leaf;
2348
2356
  const { slice, trim, onCanvas } = options;
2349
- let scale = options.scale || 1;
2350
- let pixelRatio = options.pixelRatio || 1;
2351
2357
  const smooth = options.smooth === undefined ? leafer.config.smooth : options.smooth;
2352
2358
  const contextSettings = options.contextSettings || leafer.config.contextSettings;
2353
- if (leaf.isApp) {
2354
- scale *= pixelRatio;
2355
- pixelRatio = leaf.app.pixelRatio;
2356
- }
2357
2359
  const screenshot = options.screenshot || leaf.isApp;
2358
2360
  const fill = (isLeafer && screenshot) ? (options.fill === undefined ? leaf.fill : options.fill) : options.fill;
2359
2361
  const needFill = FileHelper.isOpaqueImage(filename) || fill, matrix = new Matrix();
@@ -2387,10 +2389,21 @@ const ExportModule = {
2387
2389
  }
2388
2390
  renderBounds = leaf.getBounds('render', relative);
2389
2391
  }
2390
- const { x, y, width, height } = new Bounds(renderBounds).scale(scale);
2392
+ const scaleData = { scaleX: 1, scaleY: 1 };
2393
+ MathHelper.getScaleData(options.scale, options.size, renderBounds, scaleData);
2394
+ let pixelRatio = options.pixelRatio || 1;
2395
+ if (leaf.isApp) {
2396
+ scaleData.scaleX *= pixelRatio;
2397
+ scaleData.scaleY *= pixelRatio;
2398
+ pixelRatio = leaf.app.pixelRatio;
2399
+ }
2400
+ const { x, y, width, height } = new Bounds(renderBounds).scale(scaleData.scaleX, scaleData.scaleY);
2401
+ const renderOptions = { matrix: matrix.scale(1 / scaleData.scaleX, 1 / scaleData.scaleY).invert().translate(-x, -y).withScale(1 / scaleX * scaleData.scaleX, 1 / scaleY * scaleData.scaleY) };
2391
2402
  let canvas = Creator.canvas({ width: Math.round(width), height: Math.round(height), pixelRatio, smooth, contextSettings });
2392
- const renderOptions = { matrix: matrix.scale(1 / scale).invert().translate(-x, -y).withScale(1 / scaleX * scale, 1 / scaleY * scale) };
2403
+ let sliceLeaf;
2393
2404
  if (slice) {
2405
+ sliceLeaf = leaf;
2406
+ sliceLeaf.__worldOpacity = 0;
2394
2407
  leaf = leafer;
2395
2408
  renderOptions.bounds = canvas.bounds;
2396
2409
  }
@@ -2405,6 +2418,8 @@ const ExportModule = {
2405
2418
  leaf.__render(canvas, renderOptions);
2406
2419
  }
2407
2420
  canvas.restore();
2421
+ if (sliceLeaf)
2422
+ sliceLeaf.__updateWorldOpacity();
2408
2423
  if (trim) {
2409
2424
  trimBounds = getTrimBounds(canvas);
2410
2425
  const old = canvas, { width, height } = trimBounds;
@@ -2488,7 +2503,8 @@ Object.assign(Effect, EffectModule);
2488
2503
  Object.assign(Export, ExportModule);
2489
2504
 
2490
2505
  try {
2491
- useCanvas('wx', wx);
2506
+ if (wx)
2507
+ useCanvas('miniapp', wx);
2492
2508
  }
2493
2509
  catch (_a) { }
2494
2510