@umituz/web-canvas 1.0.1 → 1.0.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.
- package/LICENSE +21 -0
- package/README.md +32 -0
- package/dist/application/index.d.mts +1 -1
- package/dist/application/index.d.ts +1 -1
- package/dist/application/index.js +103 -40
- package/dist/application/index.mjs +2 -2
- package/dist/{chunk-BN7JTXL7.mjs → chunk-DNKRSL6D.mjs} +24 -12
- package/dist/{chunk-SF6WND7M.mjs → chunk-LOVI2LTO.mjs} +88 -28
- package/dist/{chunk-WMKPCJFI.mjs → chunk-UOGTEMIJ.mjs} +80 -29
- package/dist/index.js +186 -63
- package/dist/index.mjs +3 -3
- package/dist/infrastructure/index.d.mts +30 -6
- package/dist/infrastructure/index.d.ts +30 -6
- package/dist/infrastructure/index.js +80 -29
- package/dist/infrastructure/index.mjs +1 -1
- package/dist/presentation/index.js +186 -63
- package/dist/presentation/index.mjs +3 -3
- package/package.json +14 -3
- package/src/application/services/ScreenshotStudioService.ts +35 -12
- package/src/infrastructure/renderers/CanvasRenderer.ts +30 -3
- package/src/infrastructure/renderers/PatternRenderer.ts +43 -23
- package/src/infrastructure/renderers/ScreenshotRenderer.ts +14 -1
- package/src/infrastructure/services/DeviceConfigService.ts +18 -3
- package/src/presentation/hooks/useCanvasExport.ts +48 -8
- package/src/presentation/hooks/useReportExport.ts +38 -12
- package/src/presentation/hooks/useScreenshotStudio.ts +35 -6
|
@@ -2,6 +2,7 @@ import { a as CanvasConfig, c as CanvasDimensions, b as CanvasContextConfig, d a
|
|
|
2
2
|
|
|
3
3
|
declare class CanvasRenderer {
|
|
4
4
|
private config;
|
|
5
|
+
private imageCache;
|
|
5
6
|
constructor(config?: CanvasConfig);
|
|
6
7
|
/**
|
|
7
8
|
* Create a new canvas element
|
|
@@ -36,9 +37,17 @@ declare class CanvasRenderer {
|
|
|
36
37
|
*/
|
|
37
38
|
drawImage(ctx: CanvasRenderingContext2D, imageSource: string | HTMLImageElement, x: number, y: number, width?: number, height?: number): Promise<void>;
|
|
38
39
|
/**
|
|
39
|
-
* Load image from URL
|
|
40
|
+
* Load image from URL with caching
|
|
40
41
|
*/
|
|
41
42
|
private loadImage;
|
|
43
|
+
/**
|
|
44
|
+
* Clear image cache to free memory
|
|
45
|
+
*/
|
|
46
|
+
clearImageCache(): void;
|
|
47
|
+
/**
|
|
48
|
+
* Get cache size for monitoring
|
|
49
|
+
*/
|
|
50
|
+
getCacheSize(): number;
|
|
42
51
|
/**
|
|
43
52
|
* Create gradient
|
|
44
53
|
*/
|
|
@@ -70,24 +79,30 @@ declare class CanvasRenderer {
|
|
|
70
79
|
*/
|
|
71
80
|
|
|
72
81
|
declare class PatternRenderer {
|
|
82
|
+
private patternCanvasCache;
|
|
83
|
+
private readonly MAX_CACHE_SIZE;
|
|
73
84
|
/**
|
|
74
85
|
* Render pattern on canvas
|
|
75
86
|
*/
|
|
76
87
|
renderPattern(ctx: CanvasRenderingContext2D, pattern: BackgroundPattern, dimensions: CanvasDimensions, color?: string): void;
|
|
77
88
|
/**
|
|
78
|
-
*
|
|
89
|
+
* Clear pattern cache to free memory
|
|
90
|
+
*/
|
|
91
|
+
clearCache(): void;
|
|
92
|
+
/**
|
|
93
|
+
* Render dot pattern - optimized with batch rendering
|
|
79
94
|
*/
|
|
80
95
|
private renderDotPattern;
|
|
81
96
|
/**
|
|
82
|
-
* Render grid pattern
|
|
97
|
+
* Render grid pattern - optimized with single path
|
|
83
98
|
*/
|
|
84
99
|
private renderGridPattern;
|
|
85
100
|
/**
|
|
86
|
-
* Render line pattern
|
|
101
|
+
* Render line pattern - optimized with single path
|
|
87
102
|
*/
|
|
88
103
|
private renderLinePattern;
|
|
89
104
|
/**
|
|
90
|
-
* Render wave pattern
|
|
105
|
+
* Render wave pattern - optimized with pre-calculated values
|
|
91
106
|
*/
|
|
92
107
|
private renderWavePattern;
|
|
93
108
|
/**
|
|
@@ -105,7 +120,13 @@ declare class ScreenshotRenderer {
|
|
|
105
120
|
private canvasRenderer;
|
|
106
121
|
private patternRenderer;
|
|
107
122
|
private deviceConfigService;
|
|
123
|
+
private renderCache;
|
|
124
|
+
private readonly MAX_CACHE_SIZE;
|
|
108
125
|
constructor();
|
|
126
|
+
/**
|
|
127
|
+
* Clear render cache to free memory
|
|
128
|
+
*/
|
|
129
|
+
clearCache(): void;
|
|
109
130
|
/**
|
|
110
131
|
* Render device frame
|
|
111
132
|
*/
|
|
@@ -123,7 +144,7 @@ declare class ScreenshotRenderer {
|
|
|
123
144
|
*/
|
|
124
145
|
private renderNotch;
|
|
125
146
|
/**
|
|
126
|
-
* Render background
|
|
147
|
+
* Render background - optimized
|
|
127
148
|
*/
|
|
128
149
|
renderBackground(ctx: CanvasRenderingContext2D, design: ScreenshotDesign, dimensions: CanvasDimensions): void;
|
|
129
150
|
/**
|
|
@@ -159,6 +180,9 @@ declare class ScreenshotRenderer {
|
|
|
159
180
|
declare class DeviceConfigService {
|
|
160
181
|
private static instance;
|
|
161
182
|
private devices;
|
|
183
|
+
private phonesCache;
|
|
184
|
+
private tabletsCache;
|
|
185
|
+
private allDevicesCache;
|
|
162
186
|
private constructor();
|
|
163
187
|
static getInstance(): DeviceConfigService;
|
|
164
188
|
private initializeDevices;
|
|
@@ -49,6 +49,9 @@ var DEFAULT_DEVICE_CONFIG = {
|
|
|
49
49
|
// src/infrastructure/services/DeviceConfigService.ts
|
|
50
50
|
var DeviceConfigService = class _DeviceConfigService {
|
|
51
51
|
constructor() {
|
|
52
|
+
this.phonesCache = null;
|
|
53
|
+
this.tabletsCache = null;
|
|
54
|
+
this.allDevicesCache = null;
|
|
52
55
|
this.devices = /* @__PURE__ */ new Map();
|
|
53
56
|
this.initializeDevices();
|
|
54
57
|
}
|
|
@@ -145,13 +148,22 @@ var DeviceConfigService = class _DeviceConfigService {
|
|
|
145
148
|
return this.devices.get(deviceType);
|
|
146
149
|
}
|
|
147
150
|
getAllDevices() {
|
|
148
|
-
|
|
151
|
+
if (!this.allDevicesCache) {
|
|
152
|
+
this.allDevicesCache = Array.from(this.devices.values());
|
|
153
|
+
}
|
|
154
|
+
return this.allDevicesCache;
|
|
149
155
|
}
|
|
150
156
|
getPhones() {
|
|
151
|
-
|
|
157
|
+
if (!this.phonesCache) {
|
|
158
|
+
this.phonesCache = this.getAllDevices().filter((d) => d.isPhone);
|
|
159
|
+
}
|
|
160
|
+
return this.phonesCache;
|
|
152
161
|
}
|
|
153
162
|
getTablets() {
|
|
154
|
-
|
|
163
|
+
if (!this.tabletsCache) {
|
|
164
|
+
this.tabletsCache = this.getAllDevices().filter((d) => d.isTablet);
|
|
165
|
+
}
|
|
166
|
+
return this.tabletsCache;
|
|
155
167
|
}
|
|
156
168
|
isPhone(deviceType) {
|
|
157
169
|
const config = this.getDeviceConfig(deviceType);
|
|
@@ -181,6 +193,7 @@ var DEFAULT_CANVAS_CONFIG = {
|
|
|
181
193
|
var CanvasRenderer = class {
|
|
182
194
|
constructor(config = DEFAULT_CANVAS_CONFIG) {
|
|
183
195
|
this.config = { ...DEFAULT_CANVAS_CONFIG, ...config };
|
|
196
|
+
this.imageCache = /* @__PURE__ */ new Map();
|
|
184
197
|
}
|
|
185
198
|
/**
|
|
186
199
|
* Create a new canvas element
|
|
@@ -282,17 +295,37 @@ var CanvasRenderer = class {
|
|
|
282
295
|
}
|
|
283
296
|
}
|
|
284
297
|
/**
|
|
285
|
-
* Load image from URL
|
|
298
|
+
* Load image from URL with caching
|
|
286
299
|
*/
|
|
287
300
|
loadImage(url) {
|
|
301
|
+
if (this.imageCache.has(url)) {
|
|
302
|
+
return Promise.resolve(this.imageCache.get(url));
|
|
303
|
+
}
|
|
288
304
|
return new Promise((resolve, reject) => {
|
|
289
305
|
const img = new Image();
|
|
290
|
-
|
|
291
|
-
|
|
306
|
+
if (this.config.useCORS) {
|
|
307
|
+
img.crossOrigin = "anonymous";
|
|
308
|
+
}
|
|
309
|
+
img.onload = () => {
|
|
310
|
+
this.imageCache.set(url, img);
|
|
311
|
+
resolve(img);
|
|
312
|
+
};
|
|
292
313
|
img.onerror = () => reject(new Error(`Failed to load image: ${url}`));
|
|
293
314
|
img.src = url;
|
|
294
315
|
});
|
|
295
316
|
}
|
|
317
|
+
/**
|
|
318
|
+
* Clear image cache to free memory
|
|
319
|
+
*/
|
|
320
|
+
clearImageCache() {
|
|
321
|
+
this.imageCache.clear();
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Get cache size for monitoring
|
|
325
|
+
*/
|
|
326
|
+
getCacheSize() {
|
|
327
|
+
return this.imageCache.size;
|
|
328
|
+
}
|
|
296
329
|
/**
|
|
297
330
|
* Create gradient
|
|
298
331
|
*/
|
|
@@ -374,10 +407,15 @@ var CanvasRenderer = class {
|
|
|
374
407
|
|
|
375
408
|
// src/infrastructure/renderers/PatternRenderer.ts
|
|
376
409
|
var PatternRenderer = class {
|
|
410
|
+
constructor() {
|
|
411
|
+
this.patternCanvasCache = /* @__PURE__ */ new Map();
|
|
412
|
+
this.MAX_CACHE_SIZE = 10;
|
|
413
|
+
}
|
|
377
414
|
/**
|
|
378
415
|
* Render pattern on canvas
|
|
379
416
|
*/
|
|
380
417
|
renderPattern(ctx, pattern, dimensions, color = "#000000") {
|
|
418
|
+
if (pattern === "none") return;
|
|
381
419
|
ctx.save();
|
|
382
420
|
ctx.globalAlpha = 0.1;
|
|
383
421
|
switch (pattern) {
|
|
@@ -396,62 +434,65 @@ var PatternRenderer = class {
|
|
|
396
434
|
case "checkers":
|
|
397
435
|
this.renderCheckerPattern(ctx, dimensions, color);
|
|
398
436
|
break;
|
|
399
|
-
case "none":
|
|
400
|
-
default:
|
|
401
|
-
break;
|
|
402
437
|
}
|
|
403
438
|
ctx.restore();
|
|
404
439
|
}
|
|
405
440
|
/**
|
|
406
|
-
*
|
|
441
|
+
* Clear pattern cache to free memory
|
|
442
|
+
*/
|
|
443
|
+
clearCache() {
|
|
444
|
+
this.patternCanvasCache.clear();
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Render dot pattern - optimized with batch rendering
|
|
407
448
|
*/
|
|
408
449
|
renderDotPattern(ctx, dimensions, color) {
|
|
409
450
|
ctx.fillStyle = color;
|
|
410
451
|
const spacing = 30;
|
|
452
|
+
const radius = 2;
|
|
453
|
+
ctx.beginPath();
|
|
411
454
|
for (let x = spacing; x < dimensions.width; x += spacing) {
|
|
412
455
|
for (let y = spacing; y < dimensions.height; y += spacing) {
|
|
413
|
-
ctx.
|
|
414
|
-
ctx.arc(x, y,
|
|
415
|
-
ctx.fill();
|
|
456
|
+
ctx.moveTo(x + radius, y);
|
|
457
|
+
ctx.arc(x, y, radius, 0, Math.PI * 2);
|
|
416
458
|
}
|
|
417
459
|
}
|
|
460
|
+
ctx.fill();
|
|
418
461
|
}
|
|
419
462
|
/**
|
|
420
|
-
* Render grid pattern
|
|
463
|
+
* Render grid pattern - optimized with single path
|
|
421
464
|
*/
|
|
422
465
|
renderGridPattern(ctx, dimensions, color) {
|
|
423
466
|
ctx.strokeStyle = color;
|
|
424
467
|
ctx.lineWidth = 1;
|
|
425
468
|
const spacing = 30;
|
|
469
|
+
ctx.beginPath();
|
|
426
470
|
for (let x = 0; x <= dimensions.width; x += spacing) {
|
|
427
|
-
ctx.beginPath();
|
|
428
471
|
ctx.moveTo(x, 0);
|
|
429
472
|
ctx.lineTo(x, dimensions.height);
|
|
430
|
-
ctx.stroke();
|
|
431
473
|
}
|
|
432
474
|
for (let y = 0; y <= dimensions.height; y += spacing) {
|
|
433
|
-
ctx.beginPath();
|
|
434
475
|
ctx.moveTo(0, y);
|
|
435
476
|
ctx.lineTo(dimensions.width, y);
|
|
436
|
-
ctx.stroke();
|
|
437
477
|
}
|
|
478
|
+
ctx.stroke();
|
|
438
479
|
}
|
|
439
480
|
/**
|
|
440
|
-
* Render line pattern
|
|
481
|
+
* Render line pattern - optimized with single path
|
|
441
482
|
*/
|
|
442
483
|
renderLinePattern(ctx, dimensions, color) {
|
|
443
484
|
ctx.strokeStyle = color;
|
|
444
485
|
ctx.lineWidth = 2;
|
|
445
486
|
const spacing = 20;
|
|
487
|
+
ctx.beginPath();
|
|
446
488
|
for (let y = spacing; y < dimensions.height; y += spacing) {
|
|
447
|
-
ctx.beginPath();
|
|
448
489
|
ctx.moveTo(0, y);
|
|
449
490
|
ctx.lineTo(dimensions.width, y);
|
|
450
|
-
ctx.stroke();
|
|
451
491
|
}
|
|
492
|
+
ctx.stroke();
|
|
452
493
|
}
|
|
453
494
|
/**
|
|
454
|
-
* Render wave pattern
|
|
495
|
+
* Render wave pattern - optimized with pre-calculated values
|
|
455
496
|
*/
|
|
456
497
|
renderWavePattern(ctx, dimensions, color) {
|
|
457
498
|
ctx.strokeStyle = color;
|
|
@@ -459,15 +500,15 @@ var PatternRenderer = class {
|
|
|
459
500
|
const amplitude = 10;
|
|
460
501
|
const frequency = 0.1;
|
|
461
502
|
const spacing = 40;
|
|
503
|
+
const step = 5;
|
|
462
504
|
for (let y = spacing; y < dimensions.height; y += spacing) {
|
|
463
505
|
ctx.beginPath();
|
|
464
|
-
|
|
506
|
+
const startX = 0;
|
|
507
|
+
const startY = y + Math.sin(startX * frequency) * amplitude;
|
|
508
|
+
ctx.moveTo(startX, startY);
|
|
509
|
+
for (let x = step; x <= dimensions.width; x += step) {
|
|
465
510
|
const waveY = y + Math.sin(x * frequency) * amplitude;
|
|
466
|
-
|
|
467
|
-
ctx.moveTo(x, waveY);
|
|
468
|
-
} else {
|
|
469
|
-
ctx.lineTo(x, waveY);
|
|
470
|
-
}
|
|
511
|
+
ctx.lineTo(x, waveY);
|
|
471
512
|
}
|
|
472
513
|
ctx.stroke();
|
|
473
514
|
}
|
|
@@ -490,10 +531,20 @@ var PatternRenderer = class {
|
|
|
490
531
|
// src/infrastructure/renderers/ScreenshotRenderer.ts
|
|
491
532
|
var ScreenshotRenderer = class {
|
|
492
533
|
constructor() {
|
|
534
|
+
this.renderCache = /* @__PURE__ */ new Map();
|
|
535
|
+
this.MAX_CACHE_SIZE = 5;
|
|
493
536
|
this.canvasRenderer = new CanvasRenderer();
|
|
494
537
|
this.patternRenderer = new PatternRenderer();
|
|
495
538
|
this.deviceConfigService = DeviceConfigService.getInstance();
|
|
496
539
|
}
|
|
540
|
+
/**
|
|
541
|
+
* Clear render cache to free memory
|
|
542
|
+
*/
|
|
543
|
+
clearCache() {
|
|
544
|
+
this.renderCache.clear();
|
|
545
|
+
this.canvasRenderer.clearImageCache?.();
|
|
546
|
+
this.patternRenderer.clearCache?.();
|
|
547
|
+
}
|
|
497
548
|
/**
|
|
498
549
|
* Render device frame
|
|
499
550
|
*/
|
|
@@ -545,7 +596,7 @@ var ScreenshotRenderer = class {
|
|
|
545
596
|
ctx.fill();
|
|
546
597
|
}
|
|
547
598
|
/**
|
|
548
|
-
* Render background
|
|
599
|
+
* Render background - optimized
|
|
549
600
|
*/
|
|
550
601
|
renderBackground(ctx, design, dimensions) {
|
|
551
602
|
if (design.backgroundGradientEnd) {
|