@nmmty/lazycanvas 0.6.5 → 1.0.0-dev.3

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.
Files changed (80) hide show
  1. package/ReadMe.md +1 -1
  2. package/biome.json +41 -0
  3. package/dist/core/Interpolation.d.ts +30 -0
  4. package/dist/core/Interpolation.js +200 -0
  5. package/dist/core/Scene.d.ts +96 -0
  6. package/dist/core/Scene.js +172 -0
  7. package/dist/core/Signal.d.ts +133 -0
  8. package/dist/core/Signal.js +255 -0
  9. package/dist/core/SignalUtils.d.ts +133 -0
  10. package/dist/core/SignalUtils.js +333 -0
  11. package/dist/core/ThreadScheduler.d.ts +38 -0
  12. package/dist/core/ThreadScheduler.js +74 -0
  13. package/dist/helpers/Filters.js +1 -1
  14. package/dist/helpers/FontsList.js +18 -18
  15. package/dist/helpers/Utlis.d.ts +3 -3
  16. package/dist/helpers/Utlis.js +15 -18
  17. package/dist/helpers/index.d.ts +3 -3
  18. package/dist/index.d.ts +10 -0
  19. package/dist/index.js +10 -0
  20. package/dist/jsx-runtime.d.ts +17 -0
  21. package/dist/jsx-runtime.js +111 -0
  22. package/dist/structures/LazyCanvas.d.ts +3 -45
  23. package/dist/structures/LazyCanvas.js +11 -74
  24. package/dist/structures/components/BaseLayer.d.ts +34 -12
  25. package/dist/structures/components/BaseLayer.js +68 -35
  26. package/dist/structures/components/BezierLayer.d.ts +16 -37
  27. package/dist/structures/components/BezierLayer.js +83 -46
  28. package/dist/structures/components/{Group.d.ts → Div.d.ts} +22 -16
  29. package/dist/structures/components/{Group.js → Div.js} +38 -39
  30. package/dist/structures/components/ImageLayer.d.ts +1 -1
  31. package/dist/structures/components/ImageLayer.js +24 -25
  32. package/dist/structures/components/LineLayer.d.ts +11 -37
  33. package/dist/structures/components/LineLayer.js +42 -42
  34. package/dist/structures/components/MorphLayer.d.ts +3 -32
  35. package/dist/structures/components/MorphLayer.js +32 -46
  36. package/dist/structures/components/Path2DLayer.d.ts +4 -32
  37. package/dist/structures/components/Path2DLayer.js +28 -33
  38. package/dist/structures/components/PolygonLayer.d.ts +2 -31
  39. package/dist/structures/components/PolygonLayer.js +35 -38
  40. package/dist/structures/components/QuadraticLayer.d.ts +16 -33
  41. package/dist/structures/components/QuadraticLayer.js +80 -42
  42. package/dist/structures/components/TextLayer.d.ts +4 -33
  43. package/dist/structures/components/TextLayer.js +60 -62
  44. package/dist/structures/components/index.d.ts +10 -11
  45. package/dist/structures/components/index.js +1 -2
  46. package/dist/structures/helpers/Exporter.d.ts +13 -4
  47. package/dist/structures/helpers/Exporter.js +79 -42
  48. package/dist/structures/helpers/Font.js +1 -17
  49. package/dist/structures/helpers/Gradient.js +32 -45
  50. package/dist/structures/helpers/Link.js +2 -14
  51. package/dist/structures/helpers/Pattern.js +9 -17
  52. package/dist/structures/helpers/index.d.ts +7 -7
  53. package/dist/structures/helpers/readers/JSONReader.d.ts +4 -4
  54. package/dist/structures/helpers/readers/JSONReader.js +32 -40
  55. package/dist/structures/helpers/readers/YAMLReader.js +5 -5
  56. package/dist/structures/managers/FontsManager.js +9 -18
  57. package/dist/structures/managers/LayersManager.d.ts +18 -28
  58. package/dist/structures/managers/LayersManager.js +14 -36
  59. package/dist/structures/managers/RenderManager.d.ts +1 -15
  60. package/dist/structures/managers/RenderManager.js +17 -110
  61. package/dist/structures/managers/index.d.ts +3 -5
  62. package/dist/structures/managers/index.js +0 -2
  63. package/dist/types/enum.d.ts +1 -2
  64. package/dist/types/enum.js +1 -2
  65. package/dist/types/index.d.ts +1 -1
  66. package/dist/utils/APNGEncoder.d.ts +67 -0
  67. package/dist/utils/APNGEncoder.js +205 -0
  68. package/dist/utils/DrawUtils.d.ts +9 -0
  69. package/dist/utils/DrawUtils.js +42 -0
  70. package/dist/utils/LazyUtil.js +1 -2
  71. package/dist/utils/utils.d.ts +4 -7
  72. package/dist/utils/utils.js +133 -76
  73. package/package.json +62 -59
  74. package/dist/structures/components/ClearLayer.d.ts +0 -147
  75. package/dist/structures/components/ClearLayer.js +0 -158
  76. package/dist/structures/managers/AnimationManager.d.ts +0 -120
  77. package/dist/structures/managers/AnimationManager.js +0 -99
  78. package/dist/structures/managers/PluginManager.d.ts +0 -230
  79. package/dist/structures/managers/PluginManager.js +0 -182
  80. package/dist/types/types.d.ts +0 -107
@@ -5,14 +5,11 @@ const BaseLayer_1 = require("./BaseLayer");
5
5
  const types_1 = require("../../types");
6
6
  const LazyUtil_1 = require("../../utils/LazyUtil");
7
7
  const utils_1 = require("../../utils/utils");
8
+ const DrawUtils_1 = require("../../utils/DrawUtils");
8
9
  /**
9
10
  * Class representing a Text layer, extending the BaseLayer class.
10
11
  */
11
12
  class TextLayer extends BaseLayer_1.BaseLayer {
12
- /**
13
- * The properties of the Text Layer.
14
- */
15
- props;
16
13
  /**
17
14
  * Constructs a new TextLayer instance.
18
15
  * @param {ITextLayerProps} [props] - The properties of the Text layer.
@@ -43,9 +40,9 @@ class TextLayer extends BaseLayer_1.BaseLayer {
43
40
  setFont(familyOrConfig, size, weight) {
44
41
  if (typeof familyOrConfig === "string") {
45
42
  if (!size)
46
- throw new LazyUtil_1.LazyError('The size of the font must be provided');
43
+ throw new LazyUtil_1.LazyError("The size of the font must be provided");
47
44
  if (!weight)
48
- throw new LazyUtil_1.LazyError('The weight of the font must be provided');
45
+ throw new LazyUtil_1.LazyError("The weight of the font must be provided");
49
46
  this.props.font = {
50
47
  family: familyOrConfig,
51
48
  size,
@@ -88,9 +85,9 @@ class TextLayer extends BaseLayer_1.BaseLayer {
88
85
  */
89
86
  setColor(color, ...sub) {
90
87
  if (!color)
91
- throw new LazyUtil_1.LazyError('The color of the layer must be provided');
88
+ throw new LazyUtil_1.LazyError("The color of the layer must be provided");
92
89
  if (!(0, utils_1.isColor)(color))
93
- throw new LazyUtil_1.LazyError('The color of the layer must be a valid color');
90
+ throw new LazyUtil_1.LazyError("The color of the layer must be a valid color");
94
91
  this.props.fillStyle = color;
95
92
  if (sub && sub.length > 0) {
96
93
  this.props.subStringColors = sub;
@@ -137,13 +134,12 @@ class TextLayer extends BaseLayer_1.BaseLayer {
137
134
  setStroke(width, cap, join, dash, dashOffset, miterLimit) {
138
135
  this.props.stroke = {
139
136
  width,
140
- cap: cap || 'butt',
141
- join: join || 'miter',
137
+ cap: cap || "butt",
138
+ join: join || "miter",
142
139
  dash: dash || [],
143
140
  dashOffset: dashOffset || 0,
144
141
  miterLimit: miterLimit || 10,
145
142
  };
146
- this.props.filled = false; // Ensure filled is false when stroke is set
147
143
  return this;
148
144
  }
149
145
  /**
@@ -171,9 +167,9 @@ class TextLayer extends BaseLayer_1.BaseLayer {
171
167
  * @returns {Object} The width and height of the text.
172
168
  */
173
169
  measureText(ctx, canvas) {
174
- const w = (0, utils_1.parseToNormal)(this.props.size?.width, ctx, canvas);
175
- const h = (0, utils_1.parseToNormal)(this.props.size?.height, ctx, canvas, { width: w, height: 0 }, { vertical: true });
176
- if (this.props.multiline.enabled) {
170
+ if (this.props?.multiline?.enabled) {
171
+ const w = (0, utils_1.parseToNormal)(this.props.size?.width || "vw", ctx, canvas);
172
+ const h = (0, utils_1.parseToNormal)(this.props.size?.height || 0, ctx, canvas, { width: w, height: 0 }, { vertical: true });
177
173
  return { width: w, height: h };
178
174
  }
179
175
  else {
@@ -192,19 +188,26 @@ class TextLayer extends BaseLayer_1.BaseLayer {
192
188
  async draw(ctx, canvas, manager, debug) {
193
189
  const parcer = (0, utils_1.parser)(ctx, canvas, manager);
194
190
  const { x, y, w } = parcer.parseBatch({
195
- x: { v: this.props.x },
196
- y: { v: this.props.y, options: LazyUtil_1.defaultArg.vl(true) },
197
- w: { v: this.props.size?.width },
191
+ x: { v: this.props.position.x },
192
+ y: { v: this.props.position.y, options: LazyUtil_1.defaultArg.vl(true) },
193
+ w: { v: this.props.size?.width || "vw" },
198
194
  });
199
- const h = parcer.parse(this.props.size?.height, LazyUtil_1.defaultArg.wh(w), LazyUtil_1.defaultArg.vl(true));
195
+ const h = parcer.parse(this.props.size?.height || 0, LazyUtil_1.defaultArg.wh(w), LazyUtil_1.defaultArg.vl(true));
200
196
  if (debug)
201
- LazyUtil_1.LazyLog.log('none', `TextLayer:`, { x, y, w, h });
197
+ LazyUtil_1.LazyLog.log("none", `TextLayer:`, { x, y, w, h });
202
198
  ctx.save();
203
- (0, utils_1.transform)(ctx, this.props.transform, { width: w, height: h, x, y, type: this.type }, { text: this.props.text, textAlign: this.props.align, fontSize: this.props.font.size, multiline: this.props.multiline.enabled });
199
+ if (this.props.transform) {
200
+ (0, utils_1.transform)(ctx, this.props.transform, { width: w, height: h, x, y, type: this.type }, {
201
+ text: this.props.text,
202
+ textAlign: this.props.align,
203
+ fontSize: this.props.font.size,
204
+ multiline: this.props?.multiline?.enabled || false,
205
+ });
206
+ }
204
207
  ctx.beginPath();
205
- (0, utils_1.drawShadow)(ctx, this.props.shadow);
206
- (0, utils_1.opacity)(ctx, this.props.opacity);
207
- (0, utils_1.filters)(ctx, this.props.filter);
208
+ DrawUtils_1.DrawUtils.drawShadow(ctx, this.props.shadow);
209
+ DrawUtils_1.DrawUtils.opacity(ctx, this.props.opacity);
210
+ DrawUtils_1.DrawUtils.filters(ctx, this.props.filter);
208
211
  ctx.textAlign = this.props.align;
209
212
  if (this.props.letterSpacing)
210
213
  ctx.letterSpacing = `${this.props.letterSpacing}px`;
@@ -214,9 +217,13 @@ class TextLayer extends BaseLayer_1.BaseLayer {
214
217
  ctx.textBaseline = this.props.baseline;
215
218
  if (this.props.direction)
216
219
  ctx.direction = this.props.direction;
217
- let fillStyle = await (0, utils_1.parseFillStyle)(ctx, this.props.fillStyle, { debug, layer: { width: w, height: h, x, y, align: 'center' }, manager });
218
- if (this.props.multiline.enabled) {
219
- const words = this.props.text.split(' ');
220
+ let fillStyle = await (0, utils_1.parseFillStyle)(ctx, this.props.fillStyle, {
221
+ debug,
222
+ layer: { width: w, height: h, x, y, align: "center" },
223
+ manager,
224
+ });
225
+ if (this.props?.multiline?.enabled) {
226
+ const words = this.props.text.split(" ");
220
227
  let lines = [];
221
228
  for (let fontSize = 1; fontSize <= this.props.font.size; fontSize++) {
222
229
  let lineHeight = fontSize * (this.props.multiline.spacing || 1.1);
@@ -224,14 +231,14 @@ class TextLayer extends BaseLayer_1.BaseLayer {
224
231
  let xm = x;
225
232
  let ym = y;
226
233
  lines = [];
227
- let line = '';
234
+ let line = "";
228
235
  let charOffset = 0; // Track position in original text
229
236
  for (let word of words) {
230
- let linePlus = line + word + ' ';
237
+ let linePlus = line + word + " ";
231
238
  if (ctx.measureText(linePlus).width > w) {
232
239
  lines.push({ text: line, x: xm, y: ym, startOffset: charOffset });
233
240
  charOffset += line.length;
234
- line = word + ' ';
241
+ line = word + " ";
235
242
  ym += lineHeight;
236
243
  }
237
244
  else {
@@ -267,19 +274,12 @@ class TextLayer extends BaseLayer_1.BaseLayer {
267
274
  drawText(props, ctx, fillStyle, text, x, y, w, textOffset = 0) {
268
275
  // If no substring colors are defined, draw normally
269
276
  if (!props.subStringColors || props.subStringColors.length === 0) {
270
- if (props.filled) {
271
- ctx.fillStyle = fillStyle;
272
- ctx.fillText(text, x, y, w);
277
+ DrawUtils_1.DrawUtils.fillStyle(ctx, fillStyle, this.props.stroke);
278
+ if (props.stroke) {
279
+ ctx.strokeText(text, x, y, w);
273
280
  }
274
281
  else {
275
- ctx.strokeStyle = fillStyle;
276
- ctx.lineWidth = props.stroke?.width || 1;
277
- ctx.lineCap = props.stroke?.cap || 'butt';
278
- ctx.lineJoin = props.stroke?.join || 'miter';
279
- ctx.miterLimit = props.stroke?.miterLimit || 10;
280
- ctx.lineDashOffset = props.stroke?.dashOffset || 0;
281
- ctx.setLineDash(props.stroke?.dash || []);
282
- ctx.strokeText(text, x, y, w);
282
+ ctx.fillText(text, x, y, w);
283
283
  }
284
284
  return;
285
285
  }
@@ -288,14 +288,17 @@ class TextLayer extends BaseLayer_1.BaseLayer {
288
288
  let currentX = x;
289
289
  // Save original text alignment and set to left for manual positioning
290
290
  const originalAlign = ctx.textAlign;
291
- ctx.textAlign = 'left';
291
+ ctx.textAlign = "left";
292
292
  // Adjust starting X based on text alignment
293
293
  const alignValue = props.align;
294
- if (alignValue === types_1.TextAlign.Center || alignValue === 'center') {
294
+ if (alignValue === types_1.TextAlign.Center || alignValue === "center") {
295
295
  const totalWidth = ctx.measureText(text).width;
296
296
  currentX = x - totalWidth / 2;
297
297
  }
298
- else if (alignValue === types_1.TextAlign.Right || alignValue === 'right' || alignValue === types_1.TextAlign.End || alignValue === 'end') {
298
+ else if (alignValue === types_1.TextAlign.Right ||
299
+ alignValue === "right" ||
300
+ alignValue === types_1.TextAlign.End ||
301
+ alignValue === "end") {
299
302
  const totalWidth = ctx.measureText(text).width;
300
303
  currentX = x - totalWidth;
301
304
  }
@@ -323,16 +326,19 @@ class TextLayer extends BaseLayer_1.BaseLayer {
323
326
  text: text.substring(currentIndex, localStart),
324
327
  color: fillStyle,
325
328
  start: currentIndex,
326
- end: localStart
329
+ end: localStart,
327
330
  });
328
331
  }
329
332
  // Add colored substring
330
333
  if (localStart < localEnd) {
331
334
  segments.push({
332
335
  text: text.substring(localStart, localEnd),
333
- color: subColor.color,
336
+ color: (0, utils_1.parseFillStyle)(ctx, subColor.color, {
337
+ debug: false,
338
+ layer: { width: w, height: 0, x: 0, y: 0, align: "center" },
339
+ }),
334
340
  start: localStart,
335
- end: localEnd
341
+ end: localEnd,
336
342
  });
337
343
  currentIndex = localEnd;
338
344
  }
@@ -343,7 +349,7 @@ class TextLayer extends BaseLayer_1.BaseLayer {
343
349
  text: text.substring(currentIndex),
344
350
  color: fillStyle,
345
351
  start: currentIndex,
346
- end: textLength
352
+ end: textLength,
347
353
  });
348
354
  }
349
355
  // Draw each segment
@@ -351,19 +357,12 @@ class TextLayer extends BaseLayer_1.BaseLayer {
351
357
  if (segment.text.length === 0)
352
358
  continue;
353
359
  const segmentWidth = ctx.measureText(segment.text).width;
354
- if (props.filled) {
355
- ctx.fillStyle = segment.color;
356
- ctx.fillText(segment.text, currentX, y);
360
+ DrawUtils_1.DrawUtils.fillStyle(ctx, segment.color, this.props.stroke);
361
+ if (props.stroke) {
362
+ ctx.strokeText(segment.text, currentX, y);
357
363
  }
358
364
  else {
359
- ctx.strokeStyle = segment.color;
360
- ctx.lineWidth = props.stroke?.width || 1;
361
- ctx.lineCap = props.stroke?.cap || 'butt';
362
- ctx.lineJoin = props.stroke?.join || 'miter';
363
- ctx.miterLimit = props.stroke?.miterLimit || 10;
364
- ctx.lineDashOffset = props.stroke?.dashOffset || 0;
365
- ctx.setLineDash(props.stroke?.dash || []);
366
- ctx.strokeText(segment.text, currentX, y);
365
+ ctx.fillText(segment.text, currentX, y);
367
366
  }
368
367
  currentX += segmentWidth;
369
368
  }
@@ -377,8 +376,8 @@ class TextLayer extends BaseLayer_1.BaseLayer {
377
376
  toJSON() {
378
377
  let data = super.toJSON();
379
378
  let copy = { ...this.props };
380
- for (const key of ['x', 'y', 'size.width', 'size.height', 'fillStyle']) {
381
- if (copy[key] && typeof copy[key] === 'object' && 'toJSON' in copy[key]) {
379
+ for (const key of ["x", "y", "size.width", "size.height", "fillStyle"]) {
380
+ if (copy[key] && typeof copy[key] === "object" && "toJSON" in copy[key]) {
382
381
  copy[key] = copy[key].toJSON();
383
382
  }
384
383
  }
@@ -392,8 +391,7 @@ class TextLayer extends BaseLayer_1.BaseLayer {
392
391
  validateProps(data) {
393
392
  return {
394
393
  ...super.validateProps(data),
395
- filled: data.filled || true,
396
- fillStyle: data.fillStyle || '#000000',
394
+ fillStyle: data.fillStyle || "#000000",
397
395
  text: data.text || "",
398
396
  font: {
399
397
  family: data.font?.family || "Arial",
@@ -1,11 +1,10 @@
1
- export * from './BaseLayer';
2
- export * from './BezierLayer';
3
- export * from './ClearLayer';
4
- export * from './ImageLayer';
5
- export * from './TextLayer';
6
- export * from './MorphLayer';
7
- export * from './Group';
8
- export * from './LineLayer';
9
- export * from './QuadraticLayer';
10
- export * from './Path2DLayer';
11
- export * from './PolygonLayer';
1
+ export * from "./BaseLayer";
2
+ export * from "./BezierLayer";
3
+ export * from "./ImageLayer";
4
+ export * from "./TextLayer";
5
+ export * from "./MorphLayer";
6
+ export * from "./Div";
7
+ export * from "./LineLayer";
8
+ export * from "./QuadraticLayer";
9
+ export * from "./Path2DLayer";
10
+ export * from "./PolygonLayer";
@@ -16,11 +16,10 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./BaseLayer"), exports);
18
18
  __exportStar(require("./BezierLayer"), exports);
19
- __exportStar(require("./ClearLayer"), exports);
20
19
  __exportStar(require("./ImageLayer"), exports);
21
20
  __exportStar(require("./TextLayer"), exports);
22
21
  __exportStar(require("./MorphLayer"), exports);
23
- __exportStar(require("./Group"), exports);
22
+ __exportStar(require("./Div"), exports);
24
23
  __exportStar(require("./LineLayer"), exports);
25
24
  __exportStar(require("./QuadraticLayer"), exports);
26
25
  __exportStar(require("./Path2DLayer"), exports);
@@ -1,19 +1,24 @@
1
1
  import { IOLazyCanvas, LazyCanvas } from "../LazyCanvas";
2
2
  import { AnyExport } from "../../types";
3
3
  import { Canvas, SKRSContext2D, SvgCanvas } from "@napi-rs/canvas";
4
+ import { Scene } from "../../core/Scene";
4
5
  /**
5
- * Class responsible for exporting a LazyCanvas instance to various formats.
6
+ * Class responsible for exporting a LazyCanvas or Scene instance to various formats.
6
7
  */
7
8
  export declare class Exporter {
8
9
  /**
9
10
  * The LazyCanvas instance to be exported.
10
11
  */
11
- canvas: LazyCanvas;
12
+ canvas?: LazyCanvas;
13
+ /**
14
+ * The Scene instance to be exported.
15
+ */
16
+ scene?: Scene;
12
17
  /**
13
18
  * Constructs a new Exporter instance.
14
- * @param canvas {LazyCanvas} - The LazyCanvas instance to be exported.
19
+ * @param source {LazyCanvas | Scene} - The LazyCanvas or Scene instance to be exported.
15
20
  */
16
- constructor(canvas: LazyCanvas);
21
+ constructor(source: LazyCanvas | Scene);
17
22
  /**
18
23
  * Saves a file to the filesystem.
19
24
  * @param {any} [buffer] - The data to be saved.
@@ -34,12 +39,16 @@ export declare class Exporter {
34
39
  * @param {Object} [opts] - Optional settings.
35
40
  * @param {string} [opts.name] - The name of the file (optional).
36
41
  * @param {boolean} [opts.saveAsFile] - Whether to save the export as a file (optional).
42
+ * @param {number} [opts.duration] - Duration of the animation in seconds (Scene only).
43
+ * @param {number} [opts.fps] - Frames per second for animation (default: 60, Scene only).
37
44
  * @returns {Promise<Buffer | SKRSContext2D | Canvas | SvgCanvas | string>} The exported data.
38
45
  * @throws {LazyError} If the export type is not supported.
39
46
  */
40
47
  export(exportType: AnyExport, opts?: {
41
48
  name?: string;
42
49
  saveAsFile?: boolean;
50
+ duration?: number;
51
+ fps?: number;
43
52
  }): Promise<Buffer | SKRSContext2D | Canvas | SvgCanvas | string>;
44
53
  /**
45
54
  * Synchronously exports the canvas to the specified format.
@@ -32,6 +32,9 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
35
38
  Object.defineProperty(exports, "__esModule", { value: true });
36
39
  exports.Exporter = void 0;
37
40
  const types_1 = require("../../types");
@@ -39,20 +42,24 @@ const LazyUtil_1 = require("../../utils/LazyUtil");
39
42
  const fs = __importStar(require("fs"));
40
43
  const utils_1 = require("../../utils/utils");
41
44
  const _yaml = __importStar(require("js-yaml"));
45
+ const APNGEncoder_1 = __importDefault(require("../../utils/APNGEncoder"));
46
+ const Scene_1 = require("../../core/Scene");
42
47
  /**
43
- * Class responsible for exporting a LazyCanvas instance to various formats.
48
+ * Class responsible for exporting a LazyCanvas or Scene instance to various formats.
44
49
  */
45
50
  class Exporter {
46
- /**
47
- * The LazyCanvas instance to be exported.
48
- */
49
- canvas;
50
51
  /**
51
52
  * Constructs a new Exporter instance.
52
- * @param canvas {LazyCanvas} - The LazyCanvas instance to be exported.
53
+ * @param source {LazyCanvas | Scene} - The LazyCanvas or Scene instance to be exported.
53
54
  */
54
- constructor(canvas) {
55
- this.canvas = canvas;
55
+ constructor(source) {
56
+ if (source instanceof Scene_1.Scene) {
57
+ this.scene = source;
58
+ this.canvas = source.lazyCanvas;
59
+ }
60
+ else {
61
+ this.canvas = source;
62
+ }
56
63
  }
57
64
  /**
58
65
  * Saves a file to the filesystem.
@@ -63,9 +70,9 @@ class Exporter {
63
70
  */
64
71
  async saveFile(buffer, extension, name) {
65
72
  if (!buffer)
66
- throw new LazyUtil_1.LazyError('Buffer must be provided');
73
+ throw new LazyUtil_1.LazyError("Buffer must be provided");
67
74
  if (!extension)
68
- throw new LazyUtil_1.LazyError('Extension must be provided');
75
+ throw new LazyUtil_1.LazyError("Extension must be provided");
69
76
  fs.writeFileSync(`${name === undefined ? (0, utils_1.generateRandomName)() : name}.${extension}`, buffer);
70
77
  }
71
78
  /**
@@ -86,12 +93,15 @@ class Exporter {
86
93
  * @param {Object} [opts] - Optional settings.
87
94
  * @param {string} [opts.name] - The name of the file (optional).
88
95
  * @param {boolean} [opts.saveAsFile] - Whether to save the export as a file (optional).
96
+ * @param {number} [opts.duration] - Duration of the animation in seconds (Scene only).
97
+ * @param {number} [opts.fps] - Frames per second for animation (default: 60, Scene only).
89
98
  * @returns {Promise<Buffer | SKRSContext2D | Canvas | SvgCanvas | string>} The exported data.
90
99
  * @throws {LazyError} If the export type is not supported.
91
100
  */
92
101
  async export(exportType, opts) {
93
- // beforeExport hook
94
- this.canvas.manager.plugins.executeHook('beforeExport', this.canvas);
102
+ if (!this.canvas) {
103
+ throw new LazyUtil_1.LazyError("Canvas is not initialized");
104
+ }
95
105
  let result;
96
106
  switch (exportType) {
97
107
  case types_1.Export.CTX:
@@ -100,69 +110,94 @@ class Exporter {
100
110
  break;
101
111
  case types_1.Export.SVG:
102
112
  case "svg":
103
- result = await this.canvas.manager.render.render('svg');
113
+ result = await this.canvas.manager.render.render("svg");
104
114
  if (opts?.saveAsFile) {
105
- await this.saveFile(result, 'svg', opts.name);
115
+ await this.saveFile(result, "svg", opts.name);
106
116
  }
107
117
  break;
108
118
  case types_1.Export.BUFFER:
109
119
  case "buffer":
110
- result = await this.canvas.manager.render.render('buffer');
111
- if (opts?.saveAsFile) {
112
- await this.saveFile(result, 'png', opts.name);
120
+ if (this.scene) {
121
+ result = await this.scene.renderFirstFrame().then((frame) => frame.toBuffer("image/png"));
122
+ }
123
+ else {
124
+ result = (await this.canvas.manager.render.render("buffer"));
113
125
  }
114
- break;
115
- case types_1.Export.GIF:
116
- case "gif":
117
- result = await this.canvas.manager.render.render('buffer');
118
126
  if (opts?.saveAsFile) {
119
- await this.saveFile(result, 'gif', opts.name);
127
+ await this.saveFile(result, "png", opts.name);
120
128
  }
121
129
  break;
122
130
  case types_1.Export.WEBP:
123
131
  case "webp":
124
- result = await this.canvas.manager.render.render('buffer');
132
+ if (this.scene) {
133
+ result = await this.scene
134
+ .renderFirstFrame()
135
+ .then((frame) => frame.toBuffer("image/webp"));
136
+ }
137
+ else {
138
+ result = await this.canvas.manager.render.render("webp");
139
+ }
125
140
  if (opts?.saveAsFile) {
126
- await this.saveFile(result, 'webp', opts.name);
141
+ await this.saveFile(result, "webp", opts.name);
127
142
  }
128
143
  break;
129
- case types_1.Export.JPEG:
130
- case "jpeg":
131
- result = await this.canvas.manager.render.render('buffer');
132
- await this.saveFile(result, 'jpeg', opts?.name);
133
- break;
134
144
  case types_1.Export.JPG:
135
145
  case "jpg":
136
- const jpg = await this.canvas.manager.render.render('buffer');
137
- await this.saveFile(jpg, 'jpg', opts?.name);
138
- return jpg;
146
+ if (this.scene) {
147
+ result = await this.scene
148
+ .renderFirstFrame()
149
+ .then((frame) => frame.toBuffer("image/jpeg"));
150
+ }
151
+ else {
152
+ result = await this.canvas.manager.render.render("jpg");
153
+ }
154
+ await this.saveFile(result, "jpg", opts?.name);
155
+ return result;
139
156
  case types_1.Export.PNG:
140
157
  case "png":
141
- const png = await this.canvas.manager.render.render('buffer');
142
- await this.saveFile(png, 'png', opts?.name);
143
- return png;
158
+ if (this.scene) {
159
+ result = await this.scene.renderFirstFrame().then((frame) => frame.toBuffer("image/png"));
160
+ }
161
+ else {
162
+ result = await this.canvas.manager.render.render("png");
163
+ }
164
+ await this.saveFile(result, "png", opts?.name);
165
+ return result;
166
+ case types_1.Export.APNG:
167
+ case "apng":
168
+ if (!this.scene) {
169
+ throw new LazyUtil_1.LazyError("APNG export requires a Scene instance. Use: new Exporter(scene)");
170
+ }
171
+ const duration = opts?.duration ?? 0;
172
+ const timeNow = Date.now();
173
+ const fps = opts?.fps ?? 60;
174
+ const frameData = await this.scene.renderAnimationData(timeNow, timeNow + duration, fps);
175
+ const encoder = new APNGEncoder_1.default(this.scene.width, this.scene.height, fps).addFrames(...frameData);
176
+ const buffer = encoder.encode();
177
+ if (opts?.saveAsFile !== false) {
178
+ fs.writeFileSync(`${opts?.name ?? "animation"}.png`, buffer);
179
+ }
180
+ return buffer;
144
181
  case types_1.Export.JSON:
145
182
  case "json":
146
183
  const json = this.syncExport(exportType);
147
184
  if (opts?.saveAsFile) {
148
- await this.saveFile(JSON.stringify(json), 'json', opts.name);
185
+ await this.saveFile(JSON.stringify(json), "json", opts.name);
149
186
  }
150
187
  return JSON.stringify(json);
151
188
  case types_1.Export.CANVAS:
152
189
  case "canvas":
153
- return await this.canvas.manager.render.render(exportType);
190
+ return (await this.canvas.manager.render.render(exportType));
154
191
  case types_1.Export.YAML:
155
192
  case "yaml":
156
193
  const yaml = _yaml.dump(this.syncExport(types_1.Export.JSON));
157
194
  if (opts?.saveAsFile) {
158
- await this.saveFile(yaml, 'yaml', opts.name);
195
+ await this.saveFile(yaml, "yaml", opts.name);
159
196
  }
160
197
  return yaml;
161
198
  default:
162
199
  throw new LazyUtil_1.LazyError(`Export type ${exportType} is not supported`);
163
200
  }
164
- // afterExport hook
165
- this.canvas.manager.plugins.executeHook('afterExport', this.canvas, result);
166
201
  return result;
167
202
  }
168
203
  /**
@@ -171,13 +206,15 @@ class Exporter {
171
206
  * @returns {IOLazyCanvas | void} The exported data or void if the export type is unsupported.
172
207
  */
173
208
  syncExport(exportType) {
209
+ if (!this.canvas) {
210
+ throw new LazyUtil_1.LazyError("Canvas is not initialized");
211
+ }
174
212
  switch (exportType) {
175
213
  case types_1.Export.JSON:
176
214
  case "json":
177
215
  return {
178
216
  options: this.canvas.options,
179
- animation: this.canvas.manager.animation.options,
180
- layers: this.exportLayers(this.canvas.manager.layers)
217
+ layers: this.exportLayers(this.canvas.manager.layers),
181
218
  };
182
219
  }
183
220
  }
@@ -6,22 +6,6 @@ const types_1 = require("../../types");
6
6
  * Class representing a font with properties such as family, weight, path, and base64.
7
7
  */
8
8
  class Font {
9
- /**
10
- * The font family.
11
- */
12
- family;
13
- /**
14
- * The weight of the font.
15
- */
16
- weight;
17
- /**
18
- * The file path of the font (optional).
19
- */
20
- path;
21
- /**
22
- * The base64 representation of the font (optional).
23
- */
24
- base64;
25
9
  /**
26
10
  * Constructs a new Font instance with default values.
27
11
  */
@@ -86,7 +70,7 @@ class Font {
86
70
  family: this.family,
87
71
  weight: this.weight,
88
72
  path: this.path,
89
- base64: this.base64
73
+ base64: this.base64,
90
74
  };
91
75
  }
92
76
  }