ngx-image-cropper 7.2.1 → 8.1.0

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 (59) hide show
  1. package/README.md +56 -72
  2. package/esm2022/lib/component/cropper.state.mjs +188 -0
  3. package/esm2022/lib/component/image-cropper.component.mjs +523 -0
  4. package/esm2022/lib/interfaces/basic-event.interface.mjs +2 -0
  5. package/esm2022/lib/interfaces/cropper-options.interface.mjs +2 -0
  6. package/esm2022/lib/interfaces/index.mjs +2 -0
  7. package/esm2022/lib/interfaces/move-start.interface.mjs +8 -0
  8. package/esm2022/lib/services/crop.service.mjs +139 -0
  9. package/esm2022/lib/services/load-image.service.mjs +196 -0
  10. package/esm2022/lib/utils/cropper-position.utils.mjs +239 -0
  11. package/{esm2020 → esm2022}/lib/utils/keyboard.utils.mjs +1 -1
  12. package/esm2022/public-api.mjs +7 -0
  13. package/fesm2022/ngx-image-cropper.mjs +1500 -0
  14. package/fesm2022/ngx-image-cropper.mjs.map +1 -0
  15. package/index.d.ts +5 -7
  16. package/lib/component/cropper.state.d.ts +29 -0
  17. package/lib/component/image-cropper.component.d.ts +58 -65
  18. package/lib/interfaces/basic-event.interface.d.ts +4 -0
  19. package/lib/interfaces/cropper-options.interface.d.ts +7 -7
  20. package/lib/interfaces/index.d.ts +0 -1
  21. package/lib/interfaces/move-start.interface.d.ts +4 -6
  22. package/lib/services/crop.service.d.ts +6 -9
  23. package/lib/services/load-image.service.d.ts +5 -8
  24. package/lib/utils/cropper-position.utils.d.ts +11 -0
  25. package/lib/utils/keyboard.utils.d.ts +5 -3
  26. package/package.json +10 -18
  27. package/public-api.d.ts +6 -1
  28. package/esm2020/index.mjs +0 -8
  29. package/esm2020/lib/component/image-cropper.component.mjs +0 -635
  30. package/esm2020/lib/image-cropper.module.mjs +0 -26
  31. package/esm2020/lib/interfaces/cropper-options.interface.mjs +0 -2
  32. package/esm2020/lib/interfaces/cropper.settings.mjs +0 -54
  33. package/esm2020/lib/interfaces/index.mjs +0 -2
  34. package/esm2020/lib/interfaces/move-start.interface.mjs +0 -8
  35. package/esm2020/lib/services/crop.service.mjs +0 -147
  36. package/esm2020/lib/services/cropper-position.service.mjs +0 -200
  37. package/esm2020/lib/services/load-image.service.mjs +0 -201
  38. package/esm2020/lib/utils/hammer.utils.mjs +0 -2
  39. package/esm2020/public-api.mjs +0 -2
  40. package/fesm2015/ngx-image-cropper.mjs +0 -1484
  41. package/fesm2015/ngx-image-cropper.mjs.map +0 -1
  42. package/fesm2020/ngx-image-cropper.mjs +0 -1470
  43. package/fesm2020/ngx-image-cropper.mjs.map +0 -1
  44. package/lib/image-cropper.module.d.ts +0 -8
  45. package/lib/interfaces/cropper.settings.d.ts +0 -38
  46. package/lib/services/cropper-position.service.d.ts +0 -14
  47. package/lib/utils/hammer.utils.d.ts +0 -7
  48. package/ngx-image-cropper.d.ts +0 -5
  49. /package/{esm2020 → esm2022}/lib/interfaces/cropper-position.interface.mjs +0 -0
  50. /package/{esm2020 → esm2022}/lib/interfaces/dimensions.interface.mjs +0 -0
  51. /package/{esm2020 → esm2022}/lib/interfaces/exif-transform.interface.mjs +0 -0
  52. /package/{esm2020 → esm2022}/lib/interfaces/image-cropped-event.interface.mjs +0 -0
  53. /package/{esm2020 → esm2022}/lib/interfaces/image-transform.interface.mjs +0 -0
  54. /package/{esm2020 → esm2022}/lib/interfaces/loaded-image.interface.mjs +0 -0
  55. /package/{esm2020 → esm2022}/lib/utils/blob.utils.mjs +0 -0
  56. /package/{esm2020 → esm2022}/lib/utils/exif.utils.mjs +0 -0
  57. /package/{esm2020 → esm2022}/lib/utils/percentage.utils.mjs +0 -0
  58. /package/{esm2020 → esm2022}/lib/utils/resize.utils.mjs +0 -0
  59. /package/{esm2020 → esm2022}/ngx-image-cropper.mjs +0 -0
@@ -1,1484 +0,0 @@
1
- import { __awaiter } from 'tslib';
2
- import * as i0 from '@angular/core';
3
- import { Injectable, EventEmitter, isDevMode, Component, ChangeDetectionStrategy, Optional, Inject, ViewChild, Input, HostBinding, Output, HostListener, NgModule } from '@angular/core';
4
- import * as i4 from '@angular/platform-browser';
5
- import { HAMMER_LOADER } from '@angular/platform-browser';
6
- import { takeUntil, first } from 'rxjs/operators';
7
- import { merge, fromEvent } from 'rxjs';
8
- import * as i5 from '@angular/common';
9
- import { CommonModule } from '@angular/common';
10
-
11
- class CropperSettings {
12
- constructor() {
13
- // From options
14
- this.format = 'png';
15
- this.output = 'blob';
16
- this.maintainAspectRatio = true;
17
- this.transform = {};
18
- this.aspectRatio = 1;
19
- this.resetCropOnAspectRatioChange = true;
20
- this.resizeToWidth = 0;
21
- this.resizeToHeight = 0;
22
- this.cropperMinWidth = 0;
23
- this.cropperMinHeight = 0;
24
- this.cropperMaxHeight = 0;
25
- this.cropperMaxWidth = 0;
26
- this.cropperStaticWidth = 0;
27
- this.cropperStaticHeight = 0;
28
- this.canvasRotation = 0;
29
- this.initialStepSize = 3;
30
- this.roundCropper = false;
31
- this.onlyScaleDown = false;
32
- this.imageQuality = 92;
33
- this.autoCrop = true;
34
- this.backgroundColor = null;
35
- this.containWithinAspectRatio = false;
36
- this.hideResizeSquares = false;
37
- this.alignImage = 'center';
38
- this.cropperFrameAriaLabel = 'Crop photo';
39
- // Internal
40
- this.cropperScaledMinWidth = 20;
41
- this.cropperScaledMinHeight = 20;
42
- this.cropperScaledMaxWidth = 20;
43
- this.cropperScaledMaxHeight = 20;
44
- this.stepSize = this.initialStepSize;
45
- }
46
- setOptions(options) {
47
- Object.keys(options)
48
- .filter((k) => k in this)
49
- .forEach((k) => this[k] = options[k]);
50
- this.validateOptions();
51
- }
52
- setOptionsFromChanges(changes) {
53
- Object.keys(changes)
54
- .filter((k) => k in this)
55
- .forEach((k) => this[k] = changes[k].currentValue);
56
- this.validateOptions();
57
- }
58
- validateOptions() {
59
- if (this.maintainAspectRatio && !this.aspectRatio) {
60
- throw new Error('`aspectRatio` should > 0 when `maintainAspectRatio` is enabled');
61
- }
62
- }
63
- }
64
-
65
- var MoveTypes;
66
- (function (MoveTypes) {
67
- MoveTypes["Drag"] = "drag";
68
- MoveTypes["Move"] = "move";
69
- MoveTypes["Resize"] = "resize";
70
- MoveTypes["Pinch"] = "pinch";
71
- })(MoveTypes || (MoveTypes = {}));
72
-
73
- function getPositionForKey(key) {
74
- switch (key) {
75
- case 'ArrowUp':
76
- return 'top';
77
- case 'ArrowRight':
78
- return 'right';
79
- case 'ArrowDown':
80
- return 'bottom';
81
- case 'ArrowLeft':
82
- default:
83
- return 'left';
84
- }
85
- }
86
- function getInvertedPositionForKey(key) {
87
- switch (key) {
88
- case 'ArrowUp':
89
- return 'bottom';
90
- case 'ArrowRight':
91
- return 'left';
92
- case 'ArrowDown':
93
- return 'top';
94
- case 'ArrowLeft':
95
- default:
96
- return 'right';
97
- }
98
- }
99
- function getEventForKey(key, stepSize) {
100
- switch (key) {
101
- case 'ArrowUp':
102
- return { clientX: 0, clientY: stepSize * -1 };
103
- case 'ArrowRight':
104
- return { clientX: stepSize, clientY: 0 };
105
- case 'ArrowDown':
106
- return { clientX: 0, clientY: stepSize };
107
- case 'ArrowLeft':
108
- default:
109
- return { clientX: stepSize * -1, clientY: 0 };
110
- }
111
- }
112
-
113
- /*
114
- * Hermite resize - fast image resize/resample using Hermite filter.
115
- * https://github.com/viliusle/Hermite-resize
116
- */
117
- function resizeCanvas(canvas, width, height) {
118
- const width_source = canvas.width;
119
- const height_source = canvas.height;
120
- width = Math.round(width);
121
- height = Math.round(height);
122
- const ratio_w = width_source / width;
123
- const ratio_h = height_source / height;
124
- const ratio_w_half = Math.ceil(ratio_w / 2);
125
- const ratio_h_half = Math.ceil(ratio_h / 2);
126
- const ctx = canvas.getContext('2d');
127
- if (ctx) {
128
- const img = ctx.getImageData(0, 0, width_source, height_source);
129
- const img2 = ctx.createImageData(width, height);
130
- const data = img.data;
131
- const data2 = img2.data;
132
- for (let j = 0; j < height; j++) {
133
- for (let i = 0; i < width; i++) {
134
- const x2 = (i + j * width) * 4;
135
- const center_y = j * ratio_h;
136
- let weight = 0;
137
- let weights = 0;
138
- let weights_alpha = 0;
139
- let gx_r = 0;
140
- let gx_g = 0;
141
- let gx_b = 0;
142
- let gx_a = 0;
143
- const xx_start = Math.floor(i * ratio_w);
144
- const yy_start = Math.floor(j * ratio_h);
145
- let xx_stop = Math.ceil((i + 1) * ratio_w);
146
- let yy_stop = Math.ceil((j + 1) * ratio_h);
147
- xx_stop = Math.min(xx_stop, width_source);
148
- yy_stop = Math.min(yy_stop, height_source);
149
- for (let yy = yy_start; yy < yy_stop; yy++) {
150
- const dy = Math.abs(center_y - yy) / ratio_h_half;
151
- const center_x = i * ratio_w;
152
- const w0 = dy * dy; //pre-calc part of w
153
- for (let xx = xx_start; xx < xx_stop; xx++) {
154
- const dx = Math.abs(center_x - xx) / ratio_w_half;
155
- const w = Math.sqrt(w0 + dx * dx);
156
- if (w >= 1) {
157
- //pixel too far
158
- continue;
159
- }
160
- //hermite filter
161
- weight = 2 * w * w * w - 3 * w * w + 1;
162
- const pos_x = 4 * (xx + yy * width_source);
163
- //alpha
164
- gx_a += weight * data[pos_x + 3];
165
- weights_alpha += weight;
166
- //colors
167
- if (data[pos_x + 3] < 255)
168
- weight = weight * data[pos_x + 3] / 250;
169
- gx_r += weight * data[pos_x];
170
- gx_g += weight * data[pos_x + 1];
171
- gx_b += weight * data[pos_x + 2];
172
- weights += weight;
173
- }
174
- }
175
- data2[x2] = gx_r / weights;
176
- data2[x2 + 1] = gx_g / weights;
177
- data2[x2 + 2] = gx_b / weights;
178
- data2[x2 + 3] = gx_a / weights_alpha;
179
- }
180
- }
181
- canvas.width = width;
182
- canvas.height = height;
183
- //draw
184
- ctx.putImageData(img2, 0, 0);
185
- }
186
- }
187
-
188
- function percentage(percent, totalValue) {
189
- return (percent / 100) * totalValue;
190
- }
191
-
192
- class CropService {
193
- crop(loadedImage, cropper, settings, output, maxSize) {
194
- const imagePosition = this.getImagePosition(loadedImage, cropper, settings, maxSize);
195
- const width = imagePosition.x2 - imagePosition.x1;
196
- const height = imagePosition.y2 - imagePosition.y1;
197
- const cropCanvas = document.createElement('canvas');
198
- cropCanvas.width = width;
199
- cropCanvas.height = height;
200
- const ctx = cropCanvas.getContext('2d');
201
- if (!ctx) {
202
- return null;
203
- }
204
- if (settings.backgroundColor != null) {
205
- ctx.fillStyle = settings.backgroundColor;
206
- ctx.fillRect(0, 0, width, height);
207
- }
208
- const scaleX = (settings.transform.scale || 1) * (settings.transform.flipH ? -1 : 1);
209
- const scaleY = (settings.transform.scale || 1) * (settings.transform.flipV ? -1 : 1);
210
- const { translateH, translateV } = this.getCanvasTranslate(loadedImage, settings, maxSize);
211
- const transformedImage = loadedImage.transformed;
212
- ctx.setTransform(scaleX, 0, 0, scaleY, transformedImage.size.width / 2 + translateH, transformedImage.size.height / 2 + translateV);
213
- ctx.translate(-imagePosition.x1 / scaleX, -imagePosition.y1 / scaleY);
214
- ctx.rotate((settings.transform.rotate || 0) * Math.PI / 180);
215
- ctx.drawImage(transformedImage.image, -transformedImage.size.width / 2, -transformedImage.size.height / 2);
216
- const result = {
217
- width, height,
218
- imagePosition,
219
- cropperPosition: Object.assign({}, cropper)
220
- };
221
- if (settings.containWithinAspectRatio) {
222
- result.offsetImagePosition = this.getOffsetImagePosition(loadedImage, cropper, settings, maxSize);
223
- }
224
- const resizeRatio = this.getResizeRatio(width, height, settings);
225
- if (resizeRatio !== 1) {
226
- result.width = Math.round(width * resizeRatio);
227
- result.height = settings.maintainAspectRatio
228
- ? Math.round(result.width / settings.aspectRatio)
229
- : Math.round(height * resizeRatio);
230
- resizeCanvas(cropCanvas, result.width, result.height);
231
- }
232
- if (output === 'blob') {
233
- return this.cropToBlob(result, cropCanvas, settings);
234
- }
235
- else {
236
- result.base64 = cropCanvas.toDataURL('image/' + settings.format, this.getQuality(settings));
237
- return result;
238
- }
239
- }
240
- cropToBlob(output, cropCanvas, settings) {
241
- return __awaiter(this, void 0, void 0, function* () {
242
- output.blob = yield new Promise(resolve => cropCanvas.toBlob(resolve, 'image/' + settings.format, this.getQuality(settings)));
243
- if (output.blob) {
244
- output.objectUrl = URL.createObjectURL(output.blob);
245
- }
246
- return output;
247
- });
248
- }
249
- getCanvasTranslate(loadedImage, settings, maxSize) {
250
- if (settings.transform.translateUnit === 'px') {
251
- const ratio = this.getRatio(loadedImage, maxSize);
252
- return {
253
- translateH: (settings.transform.translateH || 0) * ratio,
254
- translateV: (settings.transform.translateV || 0) * ratio
255
- };
256
- }
257
- else {
258
- return {
259
- translateH: settings.transform.translateH ? percentage(settings.transform.translateH, loadedImage.transformed.size.width) : 0,
260
- translateV: settings.transform.translateV ? percentage(settings.transform.translateV, loadedImage.transformed.size.height) : 0
261
- };
262
- }
263
- }
264
- getRatio(loadedImage, maxSize) {
265
- return loadedImage.transformed.size.width / maxSize.width;
266
- }
267
- getImagePosition(loadedImage, cropper, settings, maxSize) {
268
- const ratio = this.getRatio(loadedImage, maxSize);
269
- const out = {
270
- x1: Math.round(cropper.x1 * ratio),
271
- y1: Math.round(cropper.y1 * ratio),
272
- x2: Math.round(cropper.x2 * ratio),
273
- y2: Math.round(cropper.y2 * ratio)
274
- };
275
- if (!settings.containWithinAspectRatio) {
276
- out.x1 = Math.max(out.x1, 0);
277
- out.y1 = Math.max(out.y1, 0);
278
- out.x2 = Math.min(out.x2, loadedImage.transformed.size.width);
279
- out.y2 = Math.min(out.y2, loadedImage.transformed.size.height);
280
- }
281
- return out;
282
- }
283
- getOffsetImagePosition(loadedImage, cropper, settings, maxSize) {
284
- const canvasRotation = settings.canvasRotation + loadedImage.exifTransform.rotate;
285
- const ratio = this.getRatio(loadedImage, maxSize);
286
- let offsetX;
287
- let offsetY;
288
- if (canvasRotation % 2) {
289
- offsetX = (loadedImage.transformed.size.width - loadedImage.original.size.height) / 2;
290
- offsetY = (loadedImage.transformed.size.height - loadedImage.original.size.width) / 2;
291
- }
292
- else {
293
- offsetX = (loadedImage.transformed.size.width - loadedImage.original.size.width) / 2;
294
- offsetY = (loadedImage.transformed.size.height - loadedImage.original.size.height) / 2;
295
- }
296
- const out = {
297
- x1: Math.round(cropper.x1 * ratio) - offsetX,
298
- y1: Math.round(cropper.y1 * ratio) - offsetY,
299
- x2: Math.round(cropper.x2 * ratio) - offsetX,
300
- y2: Math.round(cropper.y2 * ratio) - offsetY
301
- };
302
- if (!settings.containWithinAspectRatio) {
303
- out.x1 = Math.max(out.x1, 0);
304
- out.y1 = Math.max(out.y1, 0);
305
- out.x2 = Math.min(out.x2, loadedImage.transformed.size.width);
306
- out.y2 = Math.min(out.y2, loadedImage.transformed.size.height);
307
- }
308
- return out;
309
- }
310
- getResizeRatio(width, height, settings) {
311
- const ratioWidth = settings.resizeToWidth / width;
312
- const ratioHeight = settings.resizeToHeight / height;
313
- const ratios = new Array();
314
- if (settings.resizeToWidth > 0) {
315
- ratios.push(ratioWidth);
316
- }
317
- if (settings.resizeToHeight > 0) {
318
- ratios.push(ratioHeight);
319
- }
320
- const result = ratios.length === 0 ? 1 : Math.min(...ratios);
321
- if (result > 1 && !settings.onlyScaleDown) {
322
- return result;
323
- }
324
- return Math.min(result, 1);
325
- }
326
- getQuality(settings) {
327
- return Math.min(1, Math.max(0, settings.imageQuality / 100));
328
- }
329
- }
330
- CropService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: CropService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
331
- CropService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: CropService, providedIn: 'root' });
332
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: CropService, decorators: [{
333
- type: Injectable,
334
- args: [{ providedIn: 'root' }]
335
- }] });
336
-
337
- class CropperPositionService {
338
- resetCropperPosition(sourceImage, cropperPosition, settings, maxSize) {
339
- if (!(sourceImage === null || sourceImage === void 0 ? void 0 : sourceImage.nativeElement)) {
340
- return;
341
- }
342
- if (settings.cropperStaticHeight && settings.cropperStaticWidth) {
343
- cropperPosition.x1 = 0;
344
- cropperPosition.x2 = maxSize.width > settings.cropperStaticWidth ?
345
- settings.cropperStaticWidth : maxSize.width;
346
- cropperPosition.y1 = 0;
347
- cropperPosition.y2 = maxSize.height > settings.cropperStaticHeight ?
348
- settings.cropperStaticHeight : maxSize.height;
349
- }
350
- else {
351
- const cropperWidth = Math.min(settings.cropperScaledMaxWidth, maxSize.width);
352
- const cropperHeight = Math.min(settings.cropperScaledMaxHeight, maxSize.height);
353
- if (!settings.maintainAspectRatio) {
354
- cropperPosition.x1 = 0;
355
- cropperPosition.x2 = cropperWidth;
356
- cropperPosition.y1 = 0;
357
- cropperPosition.y2 = cropperHeight;
358
- }
359
- else if (maxSize.width / settings.aspectRatio < maxSize.height) {
360
- cropperPosition.x1 = 0;
361
- cropperPosition.x2 = cropperWidth;
362
- const cropperHeightWithAspectRatio = cropperWidth / settings.aspectRatio;
363
- cropperPosition.y1 = (maxSize.height - cropperHeightWithAspectRatio) / 2;
364
- cropperPosition.y2 = cropperPosition.y1 + cropperHeightWithAspectRatio;
365
- }
366
- else {
367
- cropperPosition.y1 = 0;
368
- cropperPosition.y2 = cropperHeight;
369
- const cropperWidthWithAspectRatio = cropperHeight * settings.aspectRatio;
370
- cropperPosition.x1 = (maxSize.width - cropperWidthWithAspectRatio) / 2;
371
- cropperPosition.x2 = cropperPosition.x1 + cropperWidthWithAspectRatio;
372
- }
373
- }
374
- }
375
- move(event, moveStart, cropperPosition) {
376
- const diffX = this.getClientX(event) - moveStart.clientX;
377
- const diffY = this.getClientY(event) - moveStart.clientY;
378
- cropperPosition.x1 = moveStart.x1 + diffX;
379
- cropperPosition.y1 = moveStart.y1 + diffY;
380
- cropperPosition.x2 = moveStart.x2 + diffX;
381
- cropperPosition.y2 = moveStart.y2 + diffY;
382
- }
383
- resize(event, moveStart, cropperPosition, maxSize, settings) {
384
- const moveX = this.getClientX(event) - moveStart.clientX;
385
- const moveY = this.getClientY(event) - moveStart.clientY;
386
- switch (moveStart.position) {
387
- case 'left':
388
- cropperPosition.x1 = Math.min(Math.max(moveStart.x1 + moveX, cropperPosition.x2 - settings.cropperScaledMaxWidth), cropperPosition.x2 - settings.cropperScaledMinWidth);
389
- break;
390
- case 'topleft':
391
- cropperPosition.x1 = Math.min(Math.max(moveStart.x1 + moveX, cropperPosition.x2 - settings.cropperScaledMaxWidth), cropperPosition.x2 - settings.cropperScaledMinWidth);
392
- cropperPosition.y1 = Math.min(Math.max(moveStart.y1 + moveY, cropperPosition.y2 - settings.cropperScaledMaxHeight), cropperPosition.y2 - settings.cropperScaledMinHeight);
393
- break;
394
- case 'top':
395
- cropperPosition.y1 = Math.min(Math.max(moveStart.y1 + moveY, cropperPosition.y2 - settings.cropperScaledMaxHeight), cropperPosition.y2 - settings.cropperScaledMinHeight);
396
- break;
397
- case 'topright':
398
- cropperPosition.x2 = Math.max(Math.min(moveStart.x2 + moveX, cropperPosition.x1 + settings.cropperScaledMaxWidth), cropperPosition.x1 + settings.cropperScaledMinWidth);
399
- cropperPosition.y1 = Math.min(Math.max(moveStart.y1 + moveY, cropperPosition.y2 - settings.cropperScaledMaxHeight), cropperPosition.y2 - settings.cropperScaledMinHeight);
400
- break;
401
- case 'right':
402
- cropperPosition.x2 = Math.max(Math.min(moveStart.x2 + moveX, cropperPosition.x1 + settings.cropperScaledMaxWidth), cropperPosition.x1 + settings.cropperScaledMinWidth);
403
- break;
404
- case 'bottomright':
405
- cropperPosition.x2 = Math.max(Math.min(moveStart.x2 + moveX, cropperPosition.x1 + settings.cropperScaledMaxWidth), cropperPosition.x1 + settings.cropperScaledMinWidth);
406
- cropperPosition.y2 = Math.max(Math.min(moveStart.y2 + moveY, cropperPosition.y1 + settings.cropperScaledMaxHeight), cropperPosition.y1 + settings.cropperScaledMinHeight);
407
- break;
408
- case 'bottom':
409
- cropperPosition.y2 = Math.max(Math.min(moveStart.y2 + moveY, cropperPosition.y1 + settings.cropperScaledMaxHeight), cropperPosition.y1 + settings.cropperScaledMinHeight);
410
- break;
411
- case 'bottomleft':
412
- cropperPosition.x1 = Math.min(Math.max(moveStart.x1 + moveX, cropperPosition.x2 - settings.cropperScaledMaxWidth), cropperPosition.x2 - settings.cropperScaledMinWidth);
413
- cropperPosition.y2 = Math.max(Math.min(moveStart.y2 + moveY, cropperPosition.y1 + settings.cropperScaledMaxHeight), cropperPosition.y1 + settings.cropperScaledMinHeight);
414
- break;
415
- case 'center':
416
- const scale = event.scale;
417
- const newWidth = Math.min(Math.max(settings.cropperScaledMinWidth, (Math.abs(moveStart.x2 - moveStart.x1)) * scale), settings.cropperScaledMaxWidth);
418
- const newHeight = Math.min(Math.max(settings.cropperScaledMinHeight, (Math.abs(moveStart.y2 - moveStart.y1)) * scale), settings.cropperScaledMaxHeight);
419
- cropperPosition.x1 = moveStart.clientX - newWidth / 2;
420
- cropperPosition.x2 = moveStart.clientX + newWidth / 2;
421
- cropperPosition.y1 = moveStart.clientY - newHeight / 2;
422
- cropperPosition.y2 = moveStart.clientY + newHeight / 2;
423
- if (cropperPosition.x1 < 0) {
424
- cropperPosition.x2 -= cropperPosition.x1;
425
- cropperPosition.x1 = 0;
426
- }
427
- else if (cropperPosition.x2 > maxSize.width) {
428
- cropperPosition.x1 -= (cropperPosition.x2 - maxSize.width);
429
- cropperPosition.x2 = maxSize.width;
430
- }
431
- if (cropperPosition.y1 < 0) {
432
- cropperPosition.y2 -= cropperPosition.y1;
433
- cropperPosition.y1 = 0;
434
- }
435
- else if (cropperPosition.y2 > maxSize.height) {
436
- cropperPosition.y1 -= (cropperPosition.y2 - maxSize.height);
437
- cropperPosition.y2 = maxSize.height;
438
- }
439
- break;
440
- }
441
- if (settings.maintainAspectRatio) {
442
- this.checkAspectRatio(moveStart.position, cropperPosition, maxSize, settings);
443
- }
444
- }
445
- checkAspectRatio(position, cropperPosition, maxSize, settings) {
446
- let overflowX = 0;
447
- let overflowY = 0;
448
- switch (position) {
449
- case 'top':
450
- cropperPosition.x2 = cropperPosition.x1 + (cropperPosition.y2 - cropperPosition.y1) * settings.aspectRatio;
451
- overflowX = Math.max(cropperPosition.x2 - maxSize.width, 0);
452
- overflowY = Math.max(0 - cropperPosition.y1, 0);
453
- if (overflowX > 0 || overflowY > 0) {
454
- cropperPosition.x2 -= (overflowY * settings.aspectRatio) > overflowX ? (overflowY * settings.aspectRatio) : overflowX;
455
- cropperPosition.y1 += (overflowY * settings.aspectRatio) > overflowX ? overflowY : overflowX / settings.aspectRatio;
456
- }
457
- break;
458
- case 'bottom':
459
- cropperPosition.x2 = cropperPosition.x1 + (cropperPosition.y2 - cropperPosition.y1) * settings.aspectRatio;
460
- overflowX = Math.max(cropperPosition.x2 - maxSize.width, 0);
461
- overflowY = Math.max(cropperPosition.y2 - maxSize.height, 0);
462
- if (overflowX > 0 || overflowY > 0) {
463
- cropperPosition.x2 -= (overflowY * settings.aspectRatio) > overflowX ? (overflowY * settings.aspectRatio) : overflowX;
464
- cropperPosition.y2 -= (overflowY * settings.aspectRatio) > overflowX ? overflowY : (overflowX / settings.aspectRatio);
465
- }
466
- break;
467
- case 'topleft':
468
- cropperPosition.y1 = cropperPosition.y2 - (cropperPosition.x2 - cropperPosition.x1) / settings.aspectRatio;
469
- overflowX = Math.max(0 - cropperPosition.x1, 0);
470
- overflowY = Math.max(0 - cropperPosition.y1, 0);
471
- if (overflowX > 0 || overflowY > 0) {
472
- cropperPosition.x1 += (overflowY * settings.aspectRatio) > overflowX ? (overflowY * settings.aspectRatio) : overflowX;
473
- cropperPosition.y1 += (overflowY * settings.aspectRatio) > overflowX ? overflowY : overflowX / settings.aspectRatio;
474
- }
475
- break;
476
- case 'topright':
477
- cropperPosition.y1 = cropperPosition.y2 - (cropperPosition.x2 - cropperPosition.x1) / settings.aspectRatio;
478
- overflowX = Math.max(cropperPosition.x2 - maxSize.width, 0);
479
- overflowY = Math.max(0 - cropperPosition.y1, 0);
480
- if (overflowX > 0 || overflowY > 0) {
481
- cropperPosition.x2 -= (overflowY * settings.aspectRatio) > overflowX ? (overflowY * settings.aspectRatio) : overflowX;
482
- cropperPosition.y1 += (overflowY * settings.aspectRatio) > overflowX ? overflowY : overflowX / settings.aspectRatio;
483
- }
484
- break;
485
- case 'right':
486
- case 'bottomright':
487
- cropperPosition.y2 = cropperPosition.y1 + (cropperPosition.x2 - cropperPosition.x1) / settings.aspectRatio;
488
- overflowX = Math.max(cropperPosition.x2 - maxSize.width, 0);
489
- overflowY = Math.max(cropperPosition.y2 - maxSize.height, 0);
490
- if (overflowX > 0 || overflowY > 0) {
491
- cropperPosition.x2 -= (overflowY * settings.aspectRatio) > overflowX ? (overflowY * settings.aspectRatio) : overflowX;
492
- cropperPosition.y2 -= (overflowY * settings.aspectRatio) > overflowX ? overflowY : overflowX / settings.aspectRatio;
493
- }
494
- break;
495
- case 'left':
496
- case 'bottomleft':
497
- cropperPosition.y2 = cropperPosition.y1 + (cropperPosition.x2 - cropperPosition.x1) / settings.aspectRatio;
498
- overflowX = Math.max(0 - cropperPosition.x1, 0);
499
- overflowY = Math.max(cropperPosition.y2 - maxSize.height, 0);
500
- if (overflowX > 0 || overflowY > 0) {
501
- cropperPosition.x1 += (overflowY * settings.aspectRatio) > overflowX ? (overflowY * settings.aspectRatio) : overflowX;
502
- cropperPosition.y2 -= (overflowY * settings.aspectRatio) > overflowX ? overflowY : overflowX / settings.aspectRatio;
503
- }
504
- break;
505
- case 'center':
506
- cropperPosition.x2 = cropperPosition.x1 + (cropperPosition.y2 - cropperPosition.y1) * settings.aspectRatio;
507
- cropperPosition.y2 = cropperPosition.y1 + (cropperPosition.x2 - cropperPosition.x1) / settings.aspectRatio;
508
- const overflowX1 = Math.max(0 - cropperPosition.x1, 0);
509
- const overflowX2 = Math.max(cropperPosition.x2 - maxSize.width, 0);
510
- const overflowY1 = Math.max(cropperPosition.y2 - maxSize.height, 0);
511
- const overflowY2 = Math.max(0 - cropperPosition.y1, 0);
512
- if (overflowX1 > 0 || overflowX2 > 0 || overflowY1 > 0 || overflowY2 > 0) {
513
- cropperPosition.x1 += (overflowY1 * settings.aspectRatio) > overflowX1 ? (overflowY1 * settings.aspectRatio) : overflowX1;
514
- cropperPosition.x2 -= (overflowY2 * settings.aspectRatio) > overflowX2 ? (overflowY2 * settings.aspectRatio) : overflowX2;
515
- cropperPosition.y1 += (overflowY2 * settings.aspectRatio) > overflowX2 ? overflowY2 : overflowX2 / settings.aspectRatio;
516
- cropperPosition.y2 -= (overflowY1 * settings.aspectRatio) > overflowX1 ? overflowY1 : overflowX1 / settings.aspectRatio;
517
- }
518
- break;
519
- }
520
- }
521
- getClientX(event) {
522
- var _a;
523
- return ((_a = event.touches) === null || _a === void 0 ? void 0 : _a[0].clientX) || event.clientX || 0;
524
- }
525
- getClientY(event) {
526
- var _a;
527
- return ((_a = event.touches) === null || _a === void 0 ? void 0 : _a[0].clientY) || event.clientY || 0;
528
- }
529
- }
530
- CropperPositionService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: CropperPositionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
531
- CropperPositionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: CropperPositionService, providedIn: 'root' });
532
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: CropperPositionService, decorators: [{
533
- type: Injectable,
534
- args: [{ providedIn: 'root' }]
535
- }] });
536
-
537
- // Black 2x1 JPEG, with the following meta information set:
538
- // - EXIF Orientation: 6 (Rotated 90° CCW)
539
- // Source: https://github.com/blueimp/JavaScript-Load-Image
540
- const testAutoOrientationImageURL = 'data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAA' +
541
- 'AAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA' +
542
- 'QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE' +
543
- 'BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/x' +
544
- 'ABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAA' +
545
- 'AAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==';
546
- function supportsAutomaticRotation() {
547
- return new Promise((resolve) => {
548
- const img = new Image();
549
- img.onload = () => {
550
- // Check if browser supports automatic image orientation:
551
- const supported = img.width === 1 && img.height === 2;
552
- resolve(supported);
553
- };
554
- img.src = testAutoOrientationImageURL;
555
- });
556
- }
557
- function getTransformationsFromExifData(exifRotationOrArrayBuffer) {
558
- if (typeof exifRotationOrArrayBuffer === 'object') {
559
- exifRotationOrArrayBuffer = getExifRotation(exifRotationOrArrayBuffer);
560
- }
561
- switch (exifRotationOrArrayBuffer) {
562
- case 2:
563
- return { rotate: 0, flip: true };
564
- case 3:
565
- return { rotate: 2, flip: false };
566
- case 4:
567
- return { rotate: 2, flip: true };
568
- case 5:
569
- return { rotate: 1, flip: true };
570
- case 6:
571
- return { rotate: 1, flip: false };
572
- case 7:
573
- return { rotate: 3, flip: true };
574
- case 8:
575
- return { rotate: 3, flip: false };
576
- default:
577
- return { rotate: 0, flip: false };
578
- }
579
- }
580
- function getExifRotation(arrayBuffer) {
581
- const view = new DataView(arrayBuffer);
582
- if (view.getUint16(0, false) !== 0xFFD8) {
583
- return -2;
584
- }
585
- const length = view.byteLength;
586
- let offset = 2;
587
- while (offset < length) {
588
- if (view.getUint16(offset + 2, false) <= 8)
589
- return -1;
590
- const marker = view.getUint16(offset, false);
591
- offset += 2;
592
- if (marker == 0xFFE1) {
593
- if (view.getUint32(offset += 2, false) !== 0x45786966) {
594
- return -1;
595
- }
596
- const little = view.getUint16(offset += 6, false) == 0x4949;
597
- offset += view.getUint32(offset + 4, little);
598
- const tags = view.getUint16(offset, little);
599
- offset += 2;
600
- for (let i = 0; i < tags; i++) {
601
- if (view.getUint16(offset + (i * 12), little) == 0x0112) {
602
- return view.getUint16(offset + (i * 12) + 8, little);
603
- }
604
- }
605
- }
606
- else if ((marker & 0xFF00) !== 0xFF00) {
607
- break;
608
- }
609
- else {
610
- offset += view.getUint16(offset, false);
611
- }
612
- }
613
- return -1;
614
- }
615
-
616
- class LoadImageService {
617
- constructor() {
618
- this.autoRotateSupported = supportsAutomaticRotation();
619
- }
620
- loadImageFile(file, cropperSettings) {
621
- return __awaiter(this, void 0, void 0, function* () {
622
- const arrayBuffer = yield file.arrayBuffer();
623
- return yield this.checkImageTypeAndLoadImageFromArrayBuffer(arrayBuffer, file.type, cropperSettings);
624
- });
625
- }
626
- checkImageTypeAndLoadImageFromArrayBuffer(arrayBuffer, imageType, cropperSettings) {
627
- if (!this.isValidImageType(imageType)) {
628
- return Promise.reject(new Error('Invalid image type'));
629
- }
630
- return this.loadImageFromArrayBuffer(arrayBuffer, cropperSettings, imageType);
631
- }
632
- isValidImageType(type) {
633
- return /image\/(png|jpg|jpeg|bmp|gif|tiff|svg|webp|x-icon|vnd.microsoft.icon)/.test(type);
634
- }
635
- loadImageFromURL(url, cropperSettings) {
636
- return __awaiter(this, void 0, void 0, function* () {
637
- const res = yield fetch(url);
638
- const blob = yield res.blob();
639
- const buffer = yield blob.arrayBuffer();
640
- return yield this.loadImageFromArrayBuffer(buffer, cropperSettings, blob.type);
641
- });
642
- }
643
- loadBase64Image(imageBase64, cropperSettings) {
644
- const arrayBuffer = this.base64ToArrayBuffer(imageBase64);
645
- return this.loadImageFromArrayBuffer(arrayBuffer, cropperSettings);
646
- }
647
- base64ToArrayBuffer(imageBase64) {
648
- imageBase64 = imageBase64.replace(/^data:([^;]+);base64,/gmi, '');
649
- const binaryString = atob(imageBase64);
650
- const len = binaryString.length;
651
- const bytes = new Uint8Array(len);
652
- for (let i = 0; i < len; i++) {
653
- bytes[i] = binaryString.charCodeAt(i);
654
- }
655
- return bytes.buffer;
656
- }
657
- loadImageFromArrayBuffer(arrayBuffer, cropperSettings, imageType) {
658
- return __awaiter(this, void 0, void 0, function* () {
659
- const res = yield new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
660
- try {
661
- const blob = new Blob([arrayBuffer], imageType ? { type: imageType } : undefined);
662
- const objectUrl = URL.createObjectURL(blob);
663
- const originalImage = new Image();
664
- const isSvg = imageType === 'image/svg+xml';
665
- const originalImageSize = isSvg ? yield this.getSvgImageSize(blob) : undefined;
666
- originalImage.onload = () => resolve({
667
- originalImage,
668
- originalImageSize,
669
- originalObjectUrl: objectUrl,
670
- originalArrayBuffer: arrayBuffer
671
- });
672
- originalImage.onerror = reject;
673
- originalImage.src = objectUrl;
674
- }
675
- catch (e) {
676
- reject(e);
677
- }
678
- }));
679
- return yield this.transformImageFromArrayBuffer(res, cropperSettings, res.originalImageSize != null);
680
- });
681
- }
682
- getSvgImageSize(blob) {
683
- return __awaiter(this, void 0, void 0, function* () {
684
- const parser = new DOMParser();
685
- const doc = parser.parseFromString(yield blob.text(), 'image/svg+xml');
686
- const svgElement = doc.querySelector('svg');
687
- if (!svgElement) {
688
- throw Error('Failed to parse SVG image');
689
- }
690
- const widthAttr = svgElement.getAttribute('width');
691
- const heightAttr = svgElement.getAttribute('height');
692
- if (widthAttr && heightAttr) {
693
- return null;
694
- }
695
- const viewBoxAttr = svgElement.getAttribute('viewBox')
696
- || svgElement.getAttribute('viewbox');
697
- if (viewBoxAttr) {
698
- const viewBox = viewBoxAttr.split(' ');
699
- return {
700
- width: +viewBox[2],
701
- height: +viewBox[3]
702
- };
703
- }
704
- throw Error('Failed to load SVG image. SVG must have width + height or viewBox definition.');
705
- });
706
- }
707
- transformImageFromArrayBuffer(res, cropperSettings, forceTransform = false) {
708
- var _a;
709
- return __awaiter(this, void 0, void 0, function* () {
710
- const autoRotate = yield this.autoRotateSupported;
711
- const exifTransform = getTransformationsFromExifData(autoRotate ? -1 : res.originalArrayBuffer);
712
- if (!res.originalImage || !res.originalImage.complete) {
713
- return Promise.reject(new Error('No image loaded'));
714
- }
715
- const loadedImage = {
716
- original: {
717
- objectUrl: res.originalObjectUrl,
718
- image: res.originalImage,
719
- size: (_a = res.originalImageSize) !== null && _a !== void 0 ? _a : {
720
- width: res.originalImage.naturalWidth,
721
- height: res.originalImage.naturalHeight
722
- }
723
- },
724
- exifTransform
725
- };
726
- return this.transformLoadedImage(loadedImage, cropperSettings, forceTransform);
727
- });
728
- }
729
- transformLoadedImage(loadedImage, cropperSettings, forceTransform = false) {
730
- return __awaiter(this, void 0, void 0, function* () {
731
- const canvasRotation = cropperSettings.canvasRotation + loadedImage.exifTransform.rotate;
732
- const originalSize = loadedImage.original.size;
733
- if (!forceTransform && canvasRotation === 0 && !loadedImage.exifTransform.flip && !cropperSettings.containWithinAspectRatio) {
734
- return {
735
- original: {
736
- objectUrl: loadedImage.original.objectUrl,
737
- image: loadedImage.original.image,
738
- size: Object.assign({}, originalSize)
739
- },
740
- transformed: {
741
- objectUrl: loadedImage.original.objectUrl,
742
- image: loadedImage.original.image,
743
- size: Object.assign({}, originalSize)
744
- },
745
- exifTransform: loadedImage.exifTransform
746
- };
747
- }
748
- const transformedSize = this.getTransformedSize(originalSize, loadedImage.exifTransform, cropperSettings);
749
- const canvas = document.createElement('canvas');
750
- canvas.width = transformedSize.width;
751
- canvas.height = transformedSize.height;
752
- const ctx = canvas.getContext('2d');
753
- ctx === null || ctx === void 0 ? void 0 : ctx.setTransform(loadedImage.exifTransform.flip ? -1 : 1, 0, 0, 1, canvas.width / 2, canvas.height / 2);
754
- ctx === null || ctx === void 0 ? void 0 : ctx.rotate(Math.PI * (canvasRotation / 2));
755
- ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(loadedImage.original.image, -originalSize.width / 2, -originalSize.height / 2);
756
- const blob = yield new Promise(resolve => canvas.toBlob(resolve, cropperSettings.format));
757
- if (!blob) {
758
- throw new Error('Failed to get Blob for transformed image.');
759
- }
760
- const objectUrl = URL.createObjectURL(blob);
761
- const transformedImage = yield this.loadImageFromObjectUrl(objectUrl);
762
- return {
763
- original: {
764
- objectUrl: loadedImage.original.objectUrl,
765
- image: loadedImage.original.image,
766
- size: Object.assign({}, originalSize)
767
- },
768
- transformed: {
769
- objectUrl: objectUrl,
770
- image: transformedImage,
771
- size: {
772
- width: transformedImage.width,
773
- height: transformedImage.height
774
- }
775
- },
776
- exifTransform: loadedImage.exifTransform
777
- };
778
- });
779
- }
780
- loadImageFromObjectUrl(objectUrl) {
781
- return new Promise(((resolve, reject) => {
782
- const image = new Image();
783
- image.onload = () => resolve(image);
784
- image.onerror = reject;
785
- image.src = objectUrl;
786
- }));
787
- }
788
- getTransformedSize(originalSize, exifTransform, cropperSettings) {
789
- const canvasRotation = cropperSettings.canvasRotation + exifTransform.rotate;
790
- if (cropperSettings.containWithinAspectRatio) {
791
- if (canvasRotation % 2) {
792
- const minWidthToContain = originalSize.width * cropperSettings.aspectRatio;
793
- const minHeightToContain = originalSize.height / cropperSettings.aspectRatio;
794
- return {
795
- width: Math.max(originalSize.height, minWidthToContain),
796
- height: Math.max(originalSize.width, minHeightToContain)
797
- };
798
- }
799
- else {
800
- const minWidthToContain = originalSize.height * cropperSettings.aspectRatio;
801
- const minHeightToContain = originalSize.width / cropperSettings.aspectRatio;
802
- return {
803
- width: Math.max(originalSize.width, minWidthToContain),
804
- height: Math.max(originalSize.height, minHeightToContain)
805
- };
806
- }
807
- }
808
- if (canvasRotation % 2) {
809
- return {
810
- height: originalSize.width,
811
- width: originalSize.height
812
- };
813
- }
814
- return {
815
- width: originalSize.width,
816
- height: originalSize.height
817
- };
818
- }
819
- }
820
- LoadImageService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: LoadImageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
821
- LoadImageService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: LoadImageService, providedIn: 'root' });
822
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: LoadImageService, decorators: [{
823
- type: Injectable,
824
- args: [{ providedIn: 'root' }]
825
- }] });
826
-
827
- class ImageCropperComponent {
828
- constructor(cropService, cropperPositionService, loadImageService, sanitizer, cd, zone, hammerLoader) {
829
- this.cropService = cropService;
830
- this.cropperPositionService = cropperPositionService;
831
- this.loadImageService = loadImageService;
832
- this.sanitizer = sanitizer;
833
- this.cd = cd;
834
- this.zone = zone;
835
- this.hammerLoader = hammerLoader;
836
- this.settings = new CropperSettings();
837
- this.setImageMaxSizeRetries = 0;
838
- this.resizedWhileHidden = false;
839
- this.marginLeft = '0px';
840
- this.maxSize = {
841
- width: 0,
842
- height: 0
843
- };
844
- this.moveTypes = MoveTypes;
845
- this.imageVisible = false;
846
- this.cropperFrameAriaLabel = this.settings.cropperFrameAriaLabel;
847
- this.output = this.settings.output;
848
- this.format = this.settings.format;
849
- this.transform = {};
850
- this.maintainAspectRatio = this.settings.maintainAspectRatio;
851
- this.aspectRatio = this.settings.aspectRatio;
852
- this.resetCropOnAspectRatioChange = this.settings.resetCropOnAspectRatioChange;
853
- this.resizeToWidth = this.settings.resizeToWidth;
854
- this.resizeToHeight = this.settings.resizeToHeight;
855
- this.cropperMinWidth = this.settings.cropperMinWidth;
856
- this.cropperMinHeight = this.settings.cropperMinHeight;
857
- this.cropperMaxHeight = this.settings.cropperMaxHeight;
858
- this.cropperMaxWidth = this.settings.cropperMaxWidth;
859
- this.cropperStaticWidth = this.settings.cropperStaticWidth;
860
- this.cropperStaticHeight = this.settings.cropperStaticHeight;
861
- this.canvasRotation = this.settings.canvasRotation;
862
- this.initialStepSize = this.settings.initialStepSize;
863
- this.roundCropper = this.settings.roundCropper;
864
- this.onlyScaleDown = this.settings.onlyScaleDown;
865
- this.imageQuality = this.settings.imageQuality;
866
- this.autoCrop = this.settings.autoCrop;
867
- this.backgroundColor = this.settings.backgroundColor;
868
- this.containWithinAspectRatio = this.settings.containWithinAspectRatio;
869
- this.hideResizeSquares = this.settings.hideResizeSquares;
870
- this.allowMoveImage = false;
871
- this.cropper = {
872
- x1: -100,
873
- y1: -100,
874
- x2: 10000,
875
- y2: 10000
876
- };
877
- this.alignImage = this.settings.alignImage;
878
- this.disabled = false;
879
- this.hidden = false;
880
- this.imageCropped = new EventEmitter();
881
- this.startCropImage = new EventEmitter();
882
- this.imageLoaded = new EventEmitter();
883
- this.cropperReady = new EventEmitter();
884
- this.loadImageFailed = new EventEmitter();
885
- this.transformChange = new EventEmitter();
886
- this.reset();
887
- }
888
- ngOnChanges(changes) {
889
- var _a;
890
- this.onChangesUpdateSettings(changes);
891
- this.onChangesInputImage(changes);
892
- if (((_a = this.loadedImage) === null || _a === void 0 ? void 0 : _a.original.image.complete) && (changes['containWithinAspectRatio'] || changes['canvasRotation'])) {
893
- this.loadImageService
894
- .transformLoadedImage(this.loadedImage, this.settings)
895
- .then((res) => this.setLoadedImage(res))
896
- .catch((err) => this.loadImageError(err));
897
- }
898
- if (changes['cropper'] || changes['maintainAspectRatio'] || changes['aspectRatio']) {
899
- this.setMaxSize();
900
- this.setCropperScaledMinSize();
901
- this.setCropperScaledMaxSize();
902
- if (this.maintainAspectRatio &&
903
- (this.resetCropOnAspectRatioChange || !this.aspectRatioIsCorrect()) &&
904
- (changes['maintainAspectRatio'] || changes['aspectRatio'])) {
905
- this.resetCropperPosition();
906
- }
907
- else if (changes['cropper']) {
908
- this.checkCropperPosition(false);
909
- this.doAutoCrop();
910
- }
911
- }
912
- if (changes['transform']) {
913
- this.transform = this.transform || {};
914
- this.setCssTransform();
915
- this.doAutoCrop();
916
- }
917
- if (changes['hidden'] && this.resizedWhileHidden && !this.hidden) {
918
- setTimeout(() => {
919
- this.onResize();
920
- this.resizedWhileHidden = false;
921
- });
922
- }
923
- }
924
- onChangesUpdateSettings(changes) {
925
- this.settings.setOptionsFromChanges(changes);
926
- if (this.settings.cropperStaticHeight && this.settings.cropperStaticWidth) {
927
- this.hideResizeSquares = true;
928
- this.settings.setOptions({
929
- hideResizeSquares: true,
930
- cropperMinWidth: this.settings.cropperStaticWidth,
931
- cropperMinHeight: this.settings.cropperStaticHeight,
932
- cropperMaxHeight: this.settings.cropperStaticHeight,
933
- cropperMaxWidth: this.settings.cropperStaticWidth,
934
- maintainAspectRatio: false
935
- });
936
- }
937
- }
938
- onChangesInputImage(changes) {
939
- if (changes['imageChangedEvent'] || changes['imageURL'] || changes['imageBase64'] || changes['imageFile']) {
940
- this.reset();
941
- }
942
- if (changes['imageChangedEvent'] && this.isValidImageChangedEvent()) {
943
- this.loadImageFile(this.imageChangedEvent.target.files[0]);
944
- }
945
- if (changes['imageURL'] && this.imageURL) {
946
- this.loadImageFromURL(this.imageURL);
947
- }
948
- if (changes['imageBase64'] && this.imageBase64) {
949
- this.loadBase64Image(this.imageBase64);
950
- }
951
- if (changes['imageFile'] && this.imageFile) {
952
- this.loadImageFile(this.imageFile);
953
- }
954
- }
955
- isValidImageChangedEvent() {
956
- var _a, _b, _c;
957
- return ((_c = (_b = (_a = this.imageChangedEvent) === null || _a === void 0 ? void 0 : _a.target) === null || _b === void 0 ? void 0 : _b.files) === null || _c === void 0 ? void 0 : _c.length) > 0;
958
- }
959
- setCssTransform() {
960
- var _a;
961
- const translateUnit = ((_a = this.transform) === null || _a === void 0 ? void 0 : _a.translateUnit) || '%';
962
- this.safeTransformStyle = this.sanitizer.bypassSecurityTrustStyle(`translate(${this.transform.translateH || 0}${translateUnit}, ${this.transform.translateV || 0}${translateUnit})` +
963
- ' scaleX(' + (this.transform.scale || 1) * (this.transform.flipH ? -1 : 1) + ')' +
964
- ' scaleY(' + (this.transform.scale || 1) * (this.transform.flipV ? -1 : 1) + ')' +
965
- ' rotate(' + (this.transform.rotate || 0) + 'deg)');
966
- }
967
- ngOnInit() {
968
- this.settings.stepSize = this.initialStepSize;
969
- this.activatePinchGesture();
970
- }
971
- reset() {
972
- this.imageVisible = false;
973
- this.loadedImage = undefined;
974
- this.safeImgDataUrl = 'data:image/png;base64,iVBORw0KGg'
975
- + 'oAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQYV2NgAAIAAAU'
976
- + 'AAarVyFEAAAAASUVORK5CYII=';
977
- this.moveStart = {
978
- active: false,
979
- type: null,
980
- position: null,
981
- x1: 0,
982
- y1: 0,
983
- x2: 0,
984
- y2: 0,
985
- clientX: 0,
986
- clientY: 0
987
- };
988
- this.maxSize = {
989
- width: 0,
990
- height: 0
991
- };
992
- this.cropper.x1 = -100;
993
- this.cropper.y1 = -100;
994
- this.cropper.x2 = 10000;
995
- this.cropper.y2 = 10000;
996
- }
997
- loadImageFile(file) {
998
- this.loadImageService
999
- .loadImageFile(file, this.settings)
1000
- .then((res) => this.setLoadedImage(res))
1001
- .catch((err) => this.loadImageError(err));
1002
- }
1003
- loadBase64Image(imageBase64) {
1004
- this.loadImageService
1005
- .loadBase64Image(imageBase64, this.settings)
1006
- .then((res) => this.setLoadedImage(res))
1007
- .catch((err) => this.loadImageError(err));
1008
- }
1009
- loadImageFromURL(url) {
1010
- this.loadImageService
1011
- .loadImageFromURL(url, this.settings)
1012
- .then((res) => this.setLoadedImage(res))
1013
- .catch((err) => this.loadImageError(err));
1014
- }
1015
- setLoadedImage(loadedImage) {
1016
- this.loadedImage = loadedImage;
1017
- this.safeImgDataUrl = this.sanitizer.bypassSecurityTrustResourceUrl(loadedImage.transformed.objectUrl);
1018
- this.cd.markForCheck();
1019
- }
1020
- loadImageError(error) {
1021
- console.error(error);
1022
- this.loadImageFailed.emit();
1023
- }
1024
- imageLoadedInView() {
1025
- if (this.loadedImage != null) {
1026
- this.imageLoaded.emit(this.loadedImage);
1027
- this.setImageMaxSizeRetries = 0;
1028
- setTimeout(() => this.checkImageMaxSizeRecursively());
1029
- }
1030
- }
1031
- checkImageMaxSizeRecursively() {
1032
- if (this.setImageMaxSizeRetries > 40) {
1033
- this.loadImageFailed.emit();
1034
- }
1035
- else if (this.sourceImageLoaded()) {
1036
- this.setMaxSize();
1037
- this.setCropperScaledMinSize();
1038
- this.setCropperScaledMaxSize();
1039
- this.resetCropperPosition();
1040
- this.cropperReady.emit(Object.assign({}, this.maxSize));
1041
- this.cd.markForCheck();
1042
- }
1043
- else {
1044
- this.setImageMaxSizeRetries++;
1045
- setTimeout(() => this.checkImageMaxSizeRecursively(), 50);
1046
- }
1047
- }
1048
- sourceImageLoaded() {
1049
- var _a, _b;
1050
- return ((_b = (_a = this.sourceImage) === null || _a === void 0 ? void 0 : _a.nativeElement) === null || _b === void 0 ? void 0 : _b.offsetWidth) > 0;
1051
- }
1052
- onResize() {
1053
- if (!this.loadedImage) {
1054
- return;
1055
- }
1056
- if (this.hidden) {
1057
- this.resizedWhileHidden = true;
1058
- }
1059
- else {
1060
- const oldMaxSize = Object.assign({}, this.maxSize);
1061
- this.setMaxSize();
1062
- this.resizeCropperPosition(oldMaxSize);
1063
- this.setCropperScaledMinSize();
1064
- this.setCropperScaledMaxSize();
1065
- }
1066
- }
1067
- activatePinchGesture() {
1068
- var _a;
1069
- return __awaiter(this, void 0, void 0, function* () {
1070
- // Loads HammerJS via angular APIs if configured
1071
- yield ((_a = this.hammerLoader) === null || _a === void 0 ? void 0 : _a.call(this));
1072
- const Hammer = (window === null || window === void 0 ? void 0 : window['Hammer']) || null;
1073
- if (Hammer) {
1074
- const hammer = new Hammer(this.wrapper.nativeElement);
1075
- hammer.get('pinch').set({ enable: true });
1076
- hammer.on('pinchmove', this.onPinch.bind(this));
1077
- hammer.on('pinchend', this.pinchStop.bind(this));
1078
- hammer.on('pinchstart', this.startPinch.bind(this));
1079
- }
1080
- else if (isDevMode()) {
1081
- console.warn('[NgxImageCropper] Could not find HammerJS - Pinch Gesture won\'t work');
1082
- }
1083
- });
1084
- }
1085
- resizeCropperPosition(oldMaxSize) {
1086
- if (oldMaxSize.width !== this.maxSize.width || oldMaxSize.height !== this.maxSize.height) {
1087
- this.cropper.x1 = this.cropper.x1 * this.maxSize.width / oldMaxSize.width;
1088
- this.cropper.x2 = this.cropper.x2 * this.maxSize.width / oldMaxSize.width;
1089
- this.cropper.y1 = this.cropper.y1 * this.maxSize.height / oldMaxSize.height;
1090
- this.cropper.y2 = this.cropper.y2 * this.maxSize.height / oldMaxSize.height;
1091
- }
1092
- }
1093
- resetCropperPosition() {
1094
- this.cropperPositionService.resetCropperPosition(this.sourceImage, this.cropper, this.settings, this.maxSize);
1095
- this.doAutoCrop();
1096
- this.imageVisible = true;
1097
- }
1098
- keyboardAccess(event) {
1099
- this.changeKeyboardStepSize(event);
1100
- this.keyboardMoveCropper(event);
1101
- }
1102
- changeKeyboardStepSize(event) {
1103
- const key = +event.key;
1104
- if (key >= 1 && key <= 9) {
1105
- this.settings.stepSize = key;
1106
- }
1107
- }
1108
- keyboardMoveCropper(event) {
1109
- const keyboardWhiteList = ['ArrowUp', 'ArrowDown', 'ArrowRight', 'ArrowLeft'];
1110
- if (!(keyboardWhiteList.includes(event.key))) {
1111
- return;
1112
- }
1113
- const moveType = event.shiftKey ? MoveTypes.Resize : MoveTypes.Move;
1114
- const position = event.altKey ? getInvertedPositionForKey(event.key) : getPositionForKey(event.key);
1115
- const moveEvent = getEventForKey(event.key, this.settings.stepSize);
1116
- event.preventDefault();
1117
- event.stopPropagation();
1118
- this.startMove({ clientX: 0, clientY: 0 }, moveType, position);
1119
- this.handleMouseMove(moveEvent);
1120
- this.handleMouseUp();
1121
- }
1122
- startMove(event, moveType, position = null) {
1123
- var _a, _b;
1124
- if (this.disabled
1125
- || ((_a = this.moveStart) === null || _a === void 0 ? void 0 : _a.active) && ((_b = this.moveStart) === null || _b === void 0 ? void 0 : _b.type) === MoveTypes.Pinch
1126
- || moveType === MoveTypes.Drag && !this.allowMoveImage) {
1127
- return;
1128
- }
1129
- if (event.preventDefault) {
1130
- event.preventDefault();
1131
- }
1132
- this.moveStart = Object.assign({ active: true, type: moveType, position, transform: Object.assign({}, this.transform), clientX: this.cropperPositionService.getClientX(event), clientY: this.cropperPositionService.getClientY(event) }, this.cropper);
1133
- this.initMouseMove();
1134
- }
1135
- initMouseMove() {
1136
- merge(fromEvent(document, 'mousemove'), fromEvent(document, 'touchmove')).pipe(takeUntil(merge(fromEvent(document, 'mouseup'), fromEvent(document, 'touchend')).pipe(first())))
1137
- .subscribe({
1138
- next: (event) => this.zone.run(() => {
1139
- this.handleMouseMove(event);
1140
- this.cd.markForCheck();
1141
- }),
1142
- complete: () => this.zone.run(() => {
1143
- this.handleMouseUp();
1144
- this.cd.markForCheck();
1145
- })
1146
- });
1147
- }
1148
- startPinch(event) {
1149
- if (!this.safeImgDataUrl) {
1150
- return;
1151
- }
1152
- if (event.preventDefault) {
1153
- event.preventDefault();
1154
- }
1155
- this.moveStart = Object.assign({ active: true, type: MoveTypes.Pinch, position: 'center', clientX: this.cropper.x1 + (this.cropper.x2 - this.cropper.x1) / 2, clientY: this.cropper.y1 + (this.cropper.y2 - this.cropper.y1) / 2 }, this.cropper);
1156
- }
1157
- handleMouseMove(event) {
1158
- var _a, _b;
1159
- if (this.moveStart.active) {
1160
- if (event.stopPropagation) {
1161
- event.stopPropagation();
1162
- }
1163
- if (event.preventDefault) {
1164
- event.preventDefault();
1165
- }
1166
- if (this.moveStart.type === MoveTypes.Move) {
1167
- this.cropperPositionService.move(event, this.moveStart, this.cropper);
1168
- this.checkCropperPosition(true);
1169
- }
1170
- else if (this.moveStart.type === MoveTypes.Resize) {
1171
- if (!this.cropperStaticWidth && !this.cropperStaticHeight) {
1172
- this.cropperPositionService.resize(event, this.moveStart, this.cropper, this.maxSize, this.settings);
1173
- }
1174
- this.checkCropperPosition(false);
1175
- }
1176
- else if (this.moveStart.type === MoveTypes.Drag) {
1177
- const diffX = this.cropperPositionService.getClientX(event) - this.moveStart.clientX;
1178
- const diffY = this.cropperPositionService.getClientY(event) - this.moveStart.clientY;
1179
- this.transform = Object.assign(Object.assign({}, this.transform), { translateH: (((_a = this.moveStart.transform) === null || _a === void 0 ? void 0 : _a.translateH) || 0) + diffX, translateV: (((_b = this.moveStart.transform) === null || _b === void 0 ? void 0 : _b.translateV) || 0) + diffY });
1180
- this.setCssTransform();
1181
- }
1182
- }
1183
- }
1184
- onPinch(event) {
1185
- if (this.moveStart.active) {
1186
- if (event.stopPropagation) {
1187
- event.stopPropagation();
1188
- }
1189
- if (event.preventDefault) {
1190
- event.preventDefault();
1191
- }
1192
- if (this.moveStart.type === MoveTypes.Pinch) {
1193
- this.cropperPositionService.resize(event, this.moveStart, this.cropper, this.maxSize, this.settings);
1194
- this.checkCropperPosition(false);
1195
- }
1196
- this.cd.markForCheck();
1197
- }
1198
- }
1199
- setMaxSize() {
1200
- if (this.sourceImage) {
1201
- const sourceImageStyle = getComputedStyle(this.sourceImage.nativeElement);
1202
- this.maxSize.width = parseFloat(sourceImageStyle.width);
1203
- this.maxSize.height = parseFloat(sourceImageStyle.height);
1204
- this.marginLeft = this.sanitizer.bypassSecurityTrustStyle('calc(50% - ' + this.maxSize.width / 2 + 'px)');
1205
- }
1206
- }
1207
- setCropperScaledMinSize() {
1208
- var _a, _b;
1209
- if ((_b = (_a = this.loadedImage) === null || _a === void 0 ? void 0 : _a.transformed) === null || _b === void 0 ? void 0 : _b.image) {
1210
- this.setCropperScaledMinWidth();
1211
- this.setCropperScaledMinHeight();
1212
- }
1213
- else {
1214
- this.settings.cropperScaledMinWidth = 20;
1215
- this.settings.cropperScaledMinHeight = 20;
1216
- }
1217
- }
1218
- setCropperScaledMinWidth() {
1219
- this.settings.cropperScaledMinWidth = this.cropperMinWidth > 0
1220
- ? Math.max(20, this.cropperMinWidth / this.loadedImage.transformed.image.width * this.maxSize.width)
1221
- : 20;
1222
- }
1223
- setCropperScaledMinHeight() {
1224
- if (this.maintainAspectRatio) {
1225
- this.settings.cropperScaledMinHeight = Math.max(20, this.settings.cropperScaledMinWidth / this.aspectRatio);
1226
- }
1227
- else if (this.cropperMinHeight > 0) {
1228
- this.settings.cropperScaledMinHeight = Math.max(20, this.cropperMinHeight / this.loadedImage.transformed.image.height * this.maxSize.height);
1229
- }
1230
- else {
1231
- this.settings.cropperScaledMinHeight = 20;
1232
- }
1233
- }
1234
- setCropperScaledMaxSize() {
1235
- var _a, _b;
1236
- if ((_b = (_a = this.loadedImage) === null || _a === void 0 ? void 0 : _a.transformed) === null || _b === void 0 ? void 0 : _b.image) {
1237
- const ratio = this.loadedImage.transformed.size.width / this.maxSize.width;
1238
- this.settings.cropperScaledMaxWidth = this.cropperMaxWidth > 20 ? this.cropperMaxWidth / ratio : this.maxSize.width;
1239
- this.settings.cropperScaledMaxHeight = this.cropperMaxHeight > 20 ? this.cropperMaxHeight / ratio : this.maxSize.height;
1240
- if (this.maintainAspectRatio) {
1241
- if (this.settings.cropperScaledMaxWidth > this.settings.cropperScaledMaxHeight * this.aspectRatio) {
1242
- this.settings.cropperScaledMaxWidth = this.settings.cropperScaledMaxHeight * this.aspectRatio;
1243
- }
1244
- else if (this.settings.cropperScaledMaxWidth < this.settings.cropperScaledMaxHeight * this.aspectRatio) {
1245
- this.settings.cropperScaledMaxHeight = this.settings.cropperScaledMaxWidth / this.aspectRatio;
1246
- }
1247
- }
1248
- }
1249
- else {
1250
- this.settings.cropperScaledMaxWidth = this.maxSize.width;
1251
- this.settings.cropperScaledMaxHeight = this.maxSize.height;
1252
- }
1253
- }
1254
- checkCropperPosition(maintainSize = false) {
1255
- if (this.cropper.x1 < 0) {
1256
- this.cropper.x2 -= maintainSize ? this.cropper.x1 : 0;
1257
- this.cropper.x1 = 0;
1258
- }
1259
- if (this.cropper.y1 < 0) {
1260
- this.cropper.y2 -= maintainSize ? this.cropper.y1 : 0;
1261
- this.cropper.y1 = 0;
1262
- }
1263
- if (this.cropper.x2 > this.maxSize.width) {
1264
- this.cropper.x1 -= maintainSize ? (this.cropper.x2 - this.maxSize.width) : 0;
1265
- this.cropper.x2 = this.maxSize.width;
1266
- }
1267
- if (this.cropper.y2 > this.maxSize.height) {
1268
- this.cropper.y1 -= maintainSize ? (this.cropper.y2 - this.maxSize.height) : 0;
1269
- this.cropper.y2 = this.maxSize.height;
1270
- }
1271
- }
1272
- handleMouseUp() {
1273
- var _a;
1274
- if (this.moveStart.active) {
1275
- this.moveStart.active = false;
1276
- if (((_a = this.moveStart) === null || _a === void 0 ? void 0 : _a.type) === MoveTypes.Drag) {
1277
- this.transformChange.emit(this.transform);
1278
- }
1279
- else {
1280
- this.doAutoCrop();
1281
- }
1282
- }
1283
- }
1284
- pinchStop() {
1285
- if (this.moveStart.active) {
1286
- this.moveStart.active = false;
1287
- this.doAutoCrop();
1288
- }
1289
- }
1290
- doAutoCrop() {
1291
- if (this.autoCrop) {
1292
- void this.crop();
1293
- }
1294
- }
1295
- crop(output = this.settings.output) {
1296
- var _a, _b;
1297
- if (((_b = (_a = this.loadedImage) === null || _a === void 0 ? void 0 : _a.transformed) === null || _b === void 0 ? void 0 : _b.image) != null) {
1298
- this.startCropImage.emit();
1299
- if (output === 'blob') {
1300
- return this.cropToBlob();
1301
- }
1302
- else if (output === 'base64') {
1303
- return this.cropToBase64();
1304
- }
1305
- }
1306
- return null;
1307
- }
1308
- cropToBlob() {
1309
- return new Promise((resolve, reject) => this.zone.run(() => __awaiter(this, void 0, void 0, function* () {
1310
- const result = yield this.cropService.crop(this.loadedImage, this.cropper, this.settings, 'blob', this.maxSize);
1311
- if (result) {
1312
- this.imageCropped.emit(result);
1313
- resolve(result);
1314
- }
1315
- else {
1316
- reject('Crop image failed');
1317
- }
1318
- })));
1319
- }
1320
- cropToBase64() {
1321
- const result = this.cropService.crop(this.loadedImage, this.cropper, this.settings, 'base64', this.maxSize);
1322
- if (result) {
1323
- this.imageCropped.emit(result);
1324
- return result;
1325
- }
1326
- return null;
1327
- }
1328
- aspectRatioIsCorrect() {
1329
- const currentCropAspectRatio = (this.cropper.x2 - this.cropper.x1) / (this.cropper.y2 - this.cropper.y1);
1330
- return currentCropAspectRatio === this.aspectRatio;
1331
- }
1332
- }
1333
- ImageCropperComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ImageCropperComponent, deps: [{ token: CropService }, { token: CropperPositionService }, { token: LoadImageService }, { token: i4.DomSanitizer }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: HAMMER_LOADER, optional: true }], target: i0.ɵɵFactoryTarget.Component });
1334
- ImageCropperComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: ImageCropperComponent, selector: "image-cropper", inputs: { imageChangedEvent: "imageChangedEvent", imageURL: "imageURL", imageBase64: "imageBase64", imageFile: "imageFile", imageAltText: "imageAltText", cropperFrameAriaLabel: "cropperFrameAriaLabel", output: "output", format: "format", transform: "transform", maintainAspectRatio: "maintainAspectRatio", aspectRatio: "aspectRatio", resetCropOnAspectRatioChange: "resetCropOnAspectRatioChange", resizeToWidth: "resizeToWidth", resizeToHeight: "resizeToHeight", cropperMinWidth: "cropperMinWidth", cropperMinHeight: "cropperMinHeight", cropperMaxHeight: "cropperMaxHeight", cropperMaxWidth: "cropperMaxWidth", cropperStaticWidth: "cropperStaticWidth", cropperStaticHeight: "cropperStaticHeight", canvasRotation: "canvasRotation", initialStepSize: "initialStepSize", roundCropper: "roundCropper", onlyScaleDown: "onlyScaleDown", imageQuality: "imageQuality", autoCrop: "autoCrop", backgroundColor: "backgroundColor", containWithinAspectRatio: "containWithinAspectRatio", hideResizeSquares: "hideResizeSquares", allowMoveImage: "allowMoveImage", cropper: "cropper", alignImage: "alignImage", disabled: "disabled", hidden: "hidden" }, outputs: { imageCropped: "imageCropped", startCropImage: "startCropImage", imageLoaded: "imageLoaded", cropperReady: "cropperReady", loadImageFailed: "loadImageFailed", transformChange: "transformChange" }, host: { listeners: { "window:resize": "onResize()" }, properties: { "style.text-align": "this.alignImage", "class.disabled": "this.disabled", "class.ngx-ix-hidden": "this.hidden" } }, viewQueries: [{ propertyName: "wrapper", first: true, predicate: ["wrapper"], descendants: true, static: true }, { propertyName: "sourceImage", first: true, predicate: ["sourceImage"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n [style.background]=\"imageVisible && backgroundColor\"\n #wrapper\n>\n <img\n #sourceImage\n class=\"ngx-ic-source-image\"\n role=\"presentation\"\n *ngIf=\"safeImgDataUrl\"\n [src]=\"safeImgDataUrl\"\n [style.visibility]=\"imageVisible ? 'visible' : 'hidden'\"\n [style.transform]=\"safeTransformStyle\"\n [class.ngx-ic-draggable]=\"!disabled && allowMoveImage\"\n [attr.alt]=\"imageAltText\"\n (load)=\"imageLoadedInView()\"\n (mousedown)=\"startMove($event, moveTypes.Drag)\"\n (touchstart)=\"startMove($event, moveTypes.Drag)\"\n (error)=\"loadImageError($event)\"\n >\n <div\n class=\"ngx-ic-overlay\"\n [style.width.px]=\"maxSize.width\"\n [style.height.px]=\"maxSize.height\"\n [style.margin-left]=\"alignImage === 'center' ? marginLeft : null\"\n ></div>\n <div class=\"ngx-ic-cropper\"\n *ngIf=\"imageVisible\"\n [class.ngx-ic-round]=\"roundCropper\"\n [attr.aria-label]=\"cropperFrameAriaLabel\"\n [style.top.px]=\"cropper.y1\"\n [style.left.px]=\"cropper.x1\"\n [style.width.px]=\"cropper.x2 - cropper.x1\"\n [style.height.px]=\"cropper.y2 - cropper.y1\"\n [style.margin-left]=\"alignImage === 'center' ? marginLeft : null\"\n [style.visibility]=\"imageVisible ? 'visible' : 'hidden'\"\n (keydown)=\"keyboardAccess($event)\"\n tabindex=\"0\"\n >\n <div\n (mousedown)=\"startMove($event, moveTypes.Move)\"\n (touchstart)=\"startMove($event, moveTypes.Move)\"\n class=\"ngx-ic-move\"\n role=\"presentation\">\n </div>\n <ng-container *ngIf=\"!hideResizeSquares\">\n <span class=\"ngx-ic-resize ngx-ic-topleft\"\n role=\"presentation\"\n (mousedown)=\"startMove($event, moveTypes.Resize, 'topleft')\"\n (touchstart)=\"startMove($event, moveTypes.Resize, 'topleft')\">\n <span class=\"ngx-ic-square\"></span>\n </span>\n <span class=\"ngx-ic-resize ngx-ic-top\">\n <span class=\"ngx-ic-square\"></span>\n </span>\n <span class=\"ngx-ic-resize ngx-ic-topright\"\n role=\"presentation\"\n (mousedown)=\"startMove($event, moveTypes.Resize, 'topright')\"\n (touchstart)=\"startMove($event, moveTypes.Resize, 'topright')\">\n <span class=\"ngx-ic-square\"></span>\n </span>\n <span class=\"ngx-ic-resize ngx-ic-right\">\n <span class=\"ngx-ic-square\"></span>\n </span>\n <span class=\"ngx-ic-resize ngx-ic-bottomright\"\n role=\"presentation\"\n (mousedown)=\"startMove($event, moveTypes.Resize, 'bottomright')\"\n (touchstart)=\"startMove($event, moveTypes.Resize, 'bottomright')\">\n <span class=\"ngx-ic-square\"></span>\n </span>\n <span class=\"ngx-ic-resize ngx-ic-bottom\">\n <span class=\"ngx-ic-square\"></span>\n </span>\n <span class=\"ngx-ic-resize ngx-ic-bottomleft\"\n role=\"presentation\"\n (mousedown)=\"startMove($event, moveTypes.Resize, 'bottomleft')\"\n (touchstart)=\"startMove($event, moveTypes.Resize, 'bottomleft')\">\n <span class=\"ngx-ic-square\"></span>\n </span>\n <span class=\"ngx-ic-resize ngx-ic-left\">\n <span class=\"ngx-ic-square\"></span>\n </span>\n <span class=\"ngx-ic-resize-bar ngx-ic-top\"\n role=\"presentation\"\n (mousedown)=\"startMove($event, moveTypes.Resize, 'top')\"\n (touchstart)=\"startMove($event, moveTypes.Resize, 'top')\">\n </span>\n <span class=\"ngx-ic-resize-bar ngx-ic-right\"\n role=\"presentation\"\n (mousedown)=\"startMove($event, moveTypes.Resize, 'right')\"\n (touchstart)=\"startMove($event, moveTypes.Resize, 'right')\">\n </span>\n <span class=\"ngx-ic-resize-bar ngx-ic-bottom\"\n role=\"presentation\"\n (mousedown)=\"startMove($event, moveTypes.Resize, 'bottom')\"\n (touchstart)=\"startMove($event, moveTypes.Resize, 'bottom')\">\n </span>\n <span class=\"ngx-ic-resize-bar ngx-ic-left\"\n role=\"presentation\"\n (mousedown)=\"startMove($event, moveTypes.Resize, 'left')\"\n (touchstart)=\"startMove($event, moveTypes.Resize, 'left')\">\n </span>\n </ng-container>\n </div>\n</div>\n", styles: [":host{display:flex;position:relative;width:100%;max-width:100%;max-height:100%;overflow:hidden;padding:5px;text-align:center}:host>div{width:100%;position:relative}:host>div img.ngx-ic-source-image{max-width:100%;max-height:100%;transform-origin:center}:host>div img.ngx-ic-source-image.ngx-ic-draggable{user-drag:none;-webkit-user-drag:none;user-select:none;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;cursor:grab}:host .ngx-ic-overlay{position:absolute;pointer-events:none;touch-action:none;outline:var(--cropper-overlay-color, white) solid 100vw;top:0;left:0}:host .ngx-ic-cropper{position:absolute;display:flex;color:#53535c;background:transparent;outline:rgba(255,255,255,.3) solid 100vw;outline:var(--cropper-outline-color, rgba(255, 255, 255, .3)) solid 100vw;touch-action:none}@media (orientation: portrait){:host .ngx-ic-cropper{outline-width:100vh}}:host .ngx-ic-cropper:after{position:absolute;content:\"\";inset:0;pointer-events:none;border:dashed 1px;opacity:.75;color:inherit;z-index:1}:host .ngx-ic-cropper .ngx-ic-move{width:100%;cursor:move;border:1px solid rgba(255,255,255,.5)}:host .ngx-ic-cropper:focus .ngx-ic-move{border-color:#1e90ff;border-width:2px}:host .ngx-ic-cropper .ngx-ic-resize{position:absolute;display:inline-block;line-height:6px;padding:8px;opacity:.85;z-index:1}:host .ngx-ic-cropper .ngx-ic-resize .ngx-ic-square{display:inline-block;background:#53535C;width:6px;height:6px;border:1px solid rgba(255,255,255,.5);box-sizing:content-box}:host .ngx-ic-cropper .ngx-ic-resize.ngx-ic-topleft{top:-12px;left:-12px;cursor:nwse-resize}:host .ngx-ic-cropper .ngx-ic-resize.ngx-ic-top{top:-12px;left:calc(50% - 12px);cursor:ns-resize}:host .ngx-ic-cropper .ngx-ic-resize.ngx-ic-topright{top:-12px;right:-12px;cursor:nesw-resize}:host .ngx-ic-cropper .ngx-ic-resize.ngx-ic-right{top:calc(50% - 12px);right:-12px;cursor:ew-resize}:host .ngx-ic-cropper .ngx-ic-resize.ngx-ic-bottomright{bottom:-12px;right:-12px;cursor:nwse-resize}:host .ngx-ic-cropper .ngx-ic-resize.ngx-ic-bottom{bottom:-12px;left:calc(50% - 12px);cursor:ns-resize}:host .ngx-ic-cropper .ngx-ic-resize.ngx-ic-bottomleft{bottom:-12px;left:-12px;cursor:nesw-resize}:host .ngx-ic-cropper .ngx-ic-resize.ngx-ic-left{top:calc(50% - 12px);left:-12px;cursor:ew-resize}:host .ngx-ic-cropper .ngx-ic-resize-bar{position:absolute;z-index:1}:host .ngx-ic-cropper .ngx-ic-resize-bar.ngx-ic-top{top:-11px;left:11px;width:calc(100% - 22px);height:22px;cursor:ns-resize}:host .ngx-ic-cropper .ngx-ic-resize-bar.ngx-ic-right{top:11px;right:-11px;height:calc(100% - 22px);width:22px;cursor:ew-resize}:host .ngx-ic-cropper .ngx-ic-resize-bar.ngx-ic-bottom{bottom:-11px;left:11px;width:calc(100% - 22px);height:22px;cursor:ns-resize}:host .ngx-ic-cropper .ngx-ic-resize-bar.ngx-ic-left{top:11px;left:-11px;height:calc(100% - 22px);width:22px;cursor:ew-resize}:host .ngx-ic-cropper.ngx-ic-round{outline-color:transparent}:host .ngx-ic-cropper.ngx-ic-round:after{border-radius:100%;box-shadow:0 0 0 100vw #ffffff4d;box-shadow:0 0 0 100vw var(--cropper-outline-color, rgba(255, 255, 255, .3))}@media (orientation: portrait){:host .ngx-ic-cropper.ngx-ic-round:after{box-shadow:0 0 0 100vh #ffffff4d;box-shadow:0 0 0 100vh var(--cropper-outline-color, rgba(255, 255, 255, .3))}}:host .ngx-ic-cropper.ngx-ic-round .ngx-ic-move{border-radius:100%}:host.disabled .ngx-ic-cropper .ngx-ic-resize,:host.disabled .ngx-ic-cropper .ngx-ic-resize-bar,:host.disabled .ngx-ic-cropper .ngx-ic-move{display:none}:host.ngx-ix-hidden{display:none}\n"], directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1335
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ImageCropperComponent, decorators: [{
1336
- type: Component,
1337
- args: [{ selector: 'image-cropper', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n [style.background]=\"imageVisible && backgroundColor\"\n #wrapper\n>\n <img\n #sourceImage\n class=\"ngx-ic-source-image\"\n role=\"presentation\"\n *ngIf=\"safeImgDataUrl\"\n [src]=\"safeImgDataUrl\"\n [style.visibility]=\"imageVisible ? 'visible' : 'hidden'\"\n [style.transform]=\"safeTransformStyle\"\n [class.ngx-ic-draggable]=\"!disabled && allowMoveImage\"\n [attr.alt]=\"imageAltText\"\n (load)=\"imageLoadedInView()\"\n (mousedown)=\"startMove($event, moveTypes.Drag)\"\n (touchstart)=\"startMove($event, moveTypes.Drag)\"\n (error)=\"loadImageError($event)\"\n >\n <div\n class=\"ngx-ic-overlay\"\n [style.width.px]=\"maxSize.width\"\n [style.height.px]=\"maxSize.height\"\n [style.margin-left]=\"alignImage === 'center' ? marginLeft : null\"\n ></div>\n <div class=\"ngx-ic-cropper\"\n *ngIf=\"imageVisible\"\n [class.ngx-ic-round]=\"roundCropper\"\n [attr.aria-label]=\"cropperFrameAriaLabel\"\n [style.top.px]=\"cropper.y1\"\n [style.left.px]=\"cropper.x1\"\n [style.width.px]=\"cropper.x2 - cropper.x1\"\n [style.height.px]=\"cropper.y2 - cropper.y1\"\n [style.margin-left]=\"alignImage === 'center' ? marginLeft : null\"\n [style.visibility]=\"imageVisible ? 'visible' : 'hidden'\"\n (keydown)=\"keyboardAccess($event)\"\n tabindex=\"0\"\n >\n <div\n (mousedown)=\"startMove($event, moveTypes.Move)\"\n (touchstart)=\"startMove($event, moveTypes.Move)\"\n class=\"ngx-ic-move\"\n role=\"presentation\">\n </div>\n <ng-container *ngIf=\"!hideResizeSquares\">\n <span class=\"ngx-ic-resize ngx-ic-topleft\"\n role=\"presentation\"\n (mousedown)=\"startMove($event, moveTypes.Resize, 'topleft')\"\n (touchstart)=\"startMove($event, moveTypes.Resize, 'topleft')\">\n <span class=\"ngx-ic-square\"></span>\n </span>\n <span class=\"ngx-ic-resize ngx-ic-top\">\n <span class=\"ngx-ic-square\"></span>\n </span>\n <span class=\"ngx-ic-resize ngx-ic-topright\"\n role=\"presentation\"\n (mousedown)=\"startMove($event, moveTypes.Resize, 'topright')\"\n (touchstart)=\"startMove($event, moveTypes.Resize, 'topright')\">\n <span class=\"ngx-ic-square\"></span>\n </span>\n <span class=\"ngx-ic-resize ngx-ic-right\">\n <span class=\"ngx-ic-square\"></span>\n </span>\n <span class=\"ngx-ic-resize ngx-ic-bottomright\"\n role=\"presentation\"\n (mousedown)=\"startMove($event, moveTypes.Resize, 'bottomright')\"\n (touchstart)=\"startMove($event, moveTypes.Resize, 'bottomright')\">\n <span class=\"ngx-ic-square\"></span>\n </span>\n <span class=\"ngx-ic-resize ngx-ic-bottom\">\n <span class=\"ngx-ic-square\"></span>\n </span>\n <span class=\"ngx-ic-resize ngx-ic-bottomleft\"\n role=\"presentation\"\n (mousedown)=\"startMove($event, moveTypes.Resize, 'bottomleft')\"\n (touchstart)=\"startMove($event, moveTypes.Resize, 'bottomleft')\">\n <span class=\"ngx-ic-square\"></span>\n </span>\n <span class=\"ngx-ic-resize ngx-ic-left\">\n <span class=\"ngx-ic-square\"></span>\n </span>\n <span class=\"ngx-ic-resize-bar ngx-ic-top\"\n role=\"presentation\"\n (mousedown)=\"startMove($event, moveTypes.Resize, 'top')\"\n (touchstart)=\"startMove($event, moveTypes.Resize, 'top')\">\n </span>\n <span class=\"ngx-ic-resize-bar ngx-ic-right\"\n role=\"presentation\"\n (mousedown)=\"startMove($event, moveTypes.Resize, 'right')\"\n (touchstart)=\"startMove($event, moveTypes.Resize, 'right')\">\n </span>\n <span class=\"ngx-ic-resize-bar ngx-ic-bottom\"\n role=\"presentation\"\n (mousedown)=\"startMove($event, moveTypes.Resize, 'bottom')\"\n (touchstart)=\"startMove($event, moveTypes.Resize, 'bottom')\">\n </span>\n <span class=\"ngx-ic-resize-bar ngx-ic-left\"\n role=\"presentation\"\n (mousedown)=\"startMove($event, moveTypes.Resize, 'left')\"\n (touchstart)=\"startMove($event, moveTypes.Resize, 'left')\">\n </span>\n </ng-container>\n </div>\n</div>\n", styles: [":host{display:flex;position:relative;width:100%;max-width:100%;max-height:100%;overflow:hidden;padding:5px;text-align:center}:host>div{width:100%;position:relative}:host>div img.ngx-ic-source-image{max-width:100%;max-height:100%;transform-origin:center}:host>div img.ngx-ic-source-image.ngx-ic-draggable{user-drag:none;-webkit-user-drag:none;user-select:none;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;cursor:grab}:host .ngx-ic-overlay{position:absolute;pointer-events:none;touch-action:none;outline:var(--cropper-overlay-color, white) solid 100vw;top:0;left:0}:host .ngx-ic-cropper{position:absolute;display:flex;color:#53535c;background:transparent;outline:rgba(255,255,255,.3) solid 100vw;outline:var(--cropper-outline-color, rgba(255, 255, 255, .3)) solid 100vw;touch-action:none}@media (orientation: portrait){:host .ngx-ic-cropper{outline-width:100vh}}:host .ngx-ic-cropper:after{position:absolute;content:\"\";inset:0;pointer-events:none;border:dashed 1px;opacity:.75;color:inherit;z-index:1}:host .ngx-ic-cropper .ngx-ic-move{width:100%;cursor:move;border:1px solid rgba(255,255,255,.5)}:host .ngx-ic-cropper:focus .ngx-ic-move{border-color:#1e90ff;border-width:2px}:host .ngx-ic-cropper .ngx-ic-resize{position:absolute;display:inline-block;line-height:6px;padding:8px;opacity:.85;z-index:1}:host .ngx-ic-cropper .ngx-ic-resize .ngx-ic-square{display:inline-block;background:#53535C;width:6px;height:6px;border:1px solid rgba(255,255,255,.5);box-sizing:content-box}:host .ngx-ic-cropper .ngx-ic-resize.ngx-ic-topleft{top:-12px;left:-12px;cursor:nwse-resize}:host .ngx-ic-cropper .ngx-ic-resize.ngx-ic-top{top:-12px;left:calc(50% - 12px);cursor:ns-resize}:host .ngx-ic-cropper .ngx-ic-resize.ngx-ic-topright{top:-12px;right:-12px;cursor:nesw-resize}:host .ngx-ic-cropper .ngx-ic-resize.ngx-ic-right{top:calc(50% - 12px);right:-12px;cursor:ew-resize}:host .ngx-ic-cropper .ngx-ic-resize.ngx-ic-bottomright{bottom:-12px;right:-12px;cursor:nwse-resize}:host .ngx-ic-cropper .ngx-ic-resize.ngx-ic-bottom{bottom:-12px;left:calc(50% - 12px);cursor:ns-resize}:host .ngx-ic-cropper .ngx-ic-resize.ngx-ic-bottomleft{bottom:-12px;left:-12px;cursor:nesw-resize}:host .ngx-ic-cropper .ngx-ic-resize.ngx-ic-left{top:calc(50% - 12px);left:-12px;cursor:ew-resize}:host .ngx-ic-cropper .ngx-ic-resize-bar{position:absolute;z-index:1}:host .ngx-ic-cropper .ngx-ic-resize-bar.ngx-ic-top{top:-11px;left:11px;width:calc(100% - 22px);height:22px;cursor:ns-resize}:host .ngx-ic-cropper .ngx-ic-resize-bar.ngx-ic-right{top:11px;right:-11px;height:calc(100% - 22px);width:22px;cursor:ew-resize}:host .ngx-ic-cropper .ngx-ic-resize-bar.ngx-ic-bottom{bottom:-11px;left:11px;width:calc(100% - 22px);height:22px;cursor:ns-resize}:host .ngx-ic-cropper .ngx-ic-resize-bar.ngx-ic-left{top:11px;left:-11px;height:calc(100% - 22px);width:22px;cursor:ew-resize}:host .ngx-ic-cropper.ngx-ic-round{outline-color:transparent}:host .ngx-ic-cropper.ngx-ic-round:after{border-radius:100%;box-shadow:0 0 0 100vw #ffffff4d;box-shadow:0 0 0 100vw var(--cropper-outline-color, rgba(255, 255, 255, .3))}@media (orientation: portrait){:host .ngx-ic-cropper.ngx-ic-round:after{box-shadow:0 0 0 100vh #ffffff4d;box-shadow:0 0 0 100vh var(--cropper-outline-color, rgba(255, 255, 255, .3))}}:host .ngx-ic-cropper.ngx-ic-round .ngx-ic-move{border-radius:100%}:host.disabled .ngx-ic-cropper .ngx-ic-resize,:host.disabled .ngx-ic-cropper .ngx-ic-resize-bar,:host.disabled .ngx-ic-cropper .ngx-ic-move{display:none}:host.ngx-ix-hidden{display:none}\n"] }]
1338
- }], ctorParameters: function () {
1339
- return [{ type: CropService }, { type: CropperPositionService }, { type: LoadImageService }, { type: i4.DomSanitizer }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: undefined, decorators: [{
1340
- type: Optional
1341
- }, {
1342
- type: Inject,
1343
- args: [HAMMER_LOADER]
1344
- }] }];
1345
- }, propDecorators: { wrapper: [{
1346
- type: ViewChild,
1347
- args: ['wrapper', { static: true }]
1348
- }], sourceImage: [{
1349
- type: ViewChild,
1350
- args: ['sourceImage', { static: false }]
1351
- }], imageChangedEvent: [{
1352
- type: Input
1353
- }], imageURL: [{
1354
- type: Input
1355
- }], imageBase64: [{
1356
- type: Input
1357
- }], imageFile: [{
1358
- type: Input
1359
- }], imageAltText: [{
1360
- type: Input
1361
- }], cropperFrameAriaLabel: [{
1362
- type: Input
1363
- }], output: [{
1364
- type: Input
1365
- }], format: [{
1366
- type: Input
1367
- }], transform: [{
1368
- type: Input
1369
- }], maintainAspectRatio: [{
1370
- type: Input
1371
- }], aspectRatio: [{
1372
- type: Input
1373
- }], resetCropOnAspectRatioChange: [{
1374
- type: Input
1375
- }], resizeToWidth: [{
1376
- type: Input
1377
- }], resizeToHeight: [{
1378
- type: Input
1379
- }], cropperMinWidth: [{
1380
- type: Input
1381
- }], cropperMinHeight: [{
1382
- type: Input
1383
- }], cropperMaxHeight: [{
1384
- type: Input
1385
- }], cropperMaxWidth: [{
1386
- type: Input
1387
- }], cropperStaticWidth: [{
1388
- type: Input
1389
- }], cropperStaticHeight: [{
1390
- type: Input
1391
- }], canvasRotation: [{
1392
- type: Input
1393
- }], initialStepSize: [{
1394
- type: Input
1395
- }], roundCropper: [{
1396
- type: Input
1397
- }], onlyScaleDown: [{
1398
- type: Input
1399
- }], imageQuality: [{
1400
- type: Input
1401
- }], autoCrop: [{
1402
- type: Input
1403
- }], backgroundColor: [{
1404
- type: Input
1405
- }], containWithinAspectRatio: [{
1406
- type: Input
1407
- }], hideResizeSquares: [{
1408
- type: Input
1409
- }], allowMoveImage: [{
1410
- type: Input
1411
- }], cropper: [{
1412
- type: Input
1413
- }], alignImage: [{
1414
- type: HostBinding,
1415
- args: ['style.text-align']
1416
- }, {
1417
- type: Input
1418
- }], disabled: [{
1419
- type: HostBinding,
1420
- args: ['class.disabled']
1421
- }, {
1422
- type: Input
1423
- }], hidden: [{
1424
- type: HostBinding,
1425
- args: ['class.ngx-ix-hidden']
1426
- }, {
1427
- type: Input
1428
- }], imageCropped: [{
1429
- type: Output
1430
- }], startCropImage: [{
1431
- type: Output
1432
- }], imageLoaded: [{
1433
- type: Output
1434
- }], cropperReady: [{
1435
- type: Output
1436
- }], loadImageFailed: [{
1437
- type: Output
1438
- }], transformChange: [{
1439
- type: Output
1440
- }], onResize: [{
1441
- type: HostListener,
1442
- args: ['window:resize']
1443
- }] } });
1444
-
1445
- class ImageCropperModule {
1446
- }
1447
- ImageCropperModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ImageCropperModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1448
- ImageCropperModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ImageCropperModule, declarations: [ImageCropperComponent], imports: [CommonModule], exports: [ImageCropperComponent] });
1449
- ImageCropperModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ImageCropperModule, imports: [[
1450
- CommonModule
1451
- ]] });
1452
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ImageCropperModule, decorators: [{
1453
- type: NgModule,
1454
- args: [{
1455
- imports: [
1456
- CommonModule
1457
- ],
1458
- declarations: [
1459
- ImageCropperComponent,
1460
- ],
1461
- exports: [
1462
- ImageCropperComponent
1463
- ]
1464
- }]
1465
- }] });
1466
-
1467
- function base64ToFile(base64Image) {
1468
- const split = base64Image.split(',');
1469
- const type = split[0].replace('data:', '').replace(';base64', '');
1470
- const byteString = atob(split[1]);
1471
- const ab = new ArrayBuffer(byteString.length);
1472
- const ia = new Uint8Array(ab);
1473
- for (let i = 0; i < byteString.length; i += 1) {
1474
- ia[i] = byteString.charCodeAt(i);
1475
- }
1476
- return new Blob([ab], { type });
1477
- }
1478
-
1479
- /**
1480
- * Generated bundle index. Do not edit.
1481
- */
1482
-
1483
- export { CropService, CropperSettings, ImageCropperComponent, ImageCropperModule, LoadImageService, base64ToFile, resizeCanvas };
1484
- //# sourceMappingURL=ngx-image-cropper.mjs.map