ngx-easy-image-drawing 0.0.28 → 0.0.30
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/README.md +21 -13
- package/fesm2022/ngx-easy-image-drawing.mjs +33 -38
- package/fesm2022/ngx-easy-image-drawing.mjs.map +1 -1
- package/lib/easy-image-drawing.component.d.ts +14 -10
- package/package.json +3 -5
- package/esm2022/lib/easy-image-drawing.component.mjs +0 -155
- package/esm2022/ngx-easy-image-drawing.mjs +0 -5
- package/esm2022/public-api.mjs +0 -5
package/README.md
CHANGED
|
@@ -12,6 +12,11 @@ This library provides a simple and efficient way to allow users to draw on image
|
|
|
12
12
|
npm install ngx-easy-image-drawing
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
## Versions
|
|
16
|
+
| Version | Option |
|
|
17
|
+
|----------|-----------------------------|
|
|
18
|
+
| ^0.0.30 | Angular 19. |
|
|
19
|
+
|
|
15
20
|
## Usage
|
|
16
21
|
|
|
17
22
|
1. Import
|
|
@@ -40,19 +45,20 @@ export class AppModule {}
|
|
|
40
45
|
## Options
|
|
41
46
|
|
|
42
47
|
```markdown
|
|
43
|
-
| Option
|
|
44
|
-
|
|
|
45
|
-
| height
|
|
46
|
-
| width
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
|
55
|
-
| savedImage
|
|
48
|
+
| Option | Type | Description |
|
|
49
|
+
| ------------------- | -------------------- | ------------------------------------------------------------------------------------------------- |
|
|
50
|
+
| height | number | The height of the canvas in pixels. |
|
|
51
|
+
| width | number | The width of the canvas in pixels. |
|
|
52
|
+
| src | string | The image source URL. |
|
|
53
|
+
| saveButtonColor | string | The backbackground color for save button (optional parameter). |
|
|
54
|
+
| undoButtonColor | string | The backbackground color for save button (optional parameter). |
|
|
55
|
+
| forceSizeExport | boolean | Whether to force the exported image size to match the canvas size (in the pipeline). |
|
|
56
|
+
| outputMimeType | string | The MIME type of the exported image (e.g., 'image/jpeg', 'image/png') (in the pipeline). |
|
|
57
|
+
| outputQuality | number | The quality of the exported image (0-1) (in the pipeline). |
|
|
58
|
+
| showColorPicker | boolean | Show color picker (optional parameter). True by default. |
|
|
59
|
+
| showlineWidthPicker | boolean | Show line width picker (optional parameter). True by default. |
|
|
60
|
+
| savedImage | EventEmitter<File> | An event emitted when the image is saved. The event payload is a data URL representing the image. |
|
|
61
|
+
|
|
56
62
|
```
|
|
57
63
|
|
|
58
64
|
## Example
|
|
@@ -112,6 +118,8 @@ app.component.html
|
|
|
112
118
|
[height]="canvasHeight"
|
|
113
119
|
[width]="canvasWidth"
|
|
114
120
|
[src]="uploadImageFilePreview"
|
|
121
|
+
[showColorPicker]="true"
|
|
122
|
+
[showlineWidthPicker]="true"
|
|
115
123
|
saveButtonColor="#4caf50"
|
|
116
124
|
undoButtonColor="#f44336"
|
|
117
125
|
(savedImage)="handleSavedImage($event)"
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import {
|
|
2
|
+
import { input, output, ViewChild, Component } from '@angular/core';
|
|
3
|
+
import { MatSliderModule } from '@angular/material/slider';
|
|
3
4
|
|
|
4
5
|
class EasyImageDrawing {
|
|
5
6
|
constructor(renderer) {
|
|
6
7
|
this.renderer = renderer;
|
|
7
|
-
this.width = 500;
|
|
8
|
-
this.height = 500;
|
|
9
|
-
this.
|
|
10
|
-
this.
|
|
11
|
-
this.
|
|
12
|
-
this.
|
|
13
|
-
this.
|
|
14
|
-
this.savedImage =
|
|
8
|
+
this.width = input(500);
|
|
9
|
+
this.height = input(500);
|
|
10
|
+
this.src = input("");
|
|
11
|
+
this.saveButtonColor = input("#4caf50");
|
|
12
|
+
this.undoButtonColor = input("#f44336");
|
|
13
|
+
this.showColorPicker = input(true);
|
|
14
|
+
this.showlineWidthPicker = input(true);
|
|
15
|
+
this.savedImage = output();
|
|
16
|
+
this.lineWidth = 5;
|
|
17
|
+
this.lineColor = "black";
|
|
15
18
|
this.previousPosition = { x: 0, y: 0 };
|
|
16
19
|
this.activePath = false;
|
|
17
20
|
this.eventListeners = [];
|
|
@@ -29,16 +32,24 @@ class EasyImageDrawing {
|
|
|
29
32
|
save() {
|
|
30
33
|
const dataUrl = this.canvas.nativeElement.toDataURL("image/png");
|
|
31
34
|
const blob = this._dataURItoBlob(dataUrl);
|
|
32
|
-
this.savedImage.
|
|
35
|
+
this.savedImage.emit(new File([blob], "image.png"));
|
|
33
36
|
}
|
|
34
37
|
clear() {
|
|
35
|
-
this.context.clearRect(0, 0, this.width, this.height);
|
|
38
|
+
this.context.clearRect(0, 0, this.width(), this.height());
|
|
36
39
|
const image = new Image();
|
|
37
|
-
image.src = this.src;
|
|
40
|
+
image.src = this.src();
|
|
38
41
|
image.onload = () => {
|
|
39
|
-
this.context.drawImage(image, 0, 0, this.width, this.height);
|
|
42
|
+
this.context.drawImage(image, 0, 0, this.width(), this.height());
|
|
40
43
|
};
|
|
41
44
|
}
|
|
45
|
+
onColorSelected(color) {
|
|
46
|
+
this.context.strokeStyle = color;
|
|
47
|
+
}
|
|
48
|
+
onLineWidthChanged(event) {
|
|
49
|
+
if (event?.target?.value) {
|
|
50
|
+
this.context.lineWidth = event.target.value;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
42
53
|
_dataURItoBlob(dataUrl) {
|
|
43
54
|
const byteString = atob(dataUrl.split(",")[1]);
|
|
44
55
|
const mimeString = dataUrl.split(",")[0].split(":")[1].split(";")[0];
|
|
@@ -68,8 +79,8 @@ class EasyImageDrawing {
|
|
|
68
79
|
_setCanvas() {
|
|
69
80
|
if (!this.canvas)
|
|
70
81
|
return;
|
|
71
|
-
this.canvas.nativeElement.width = this.width;
|
|
72
|
-
this.canvas.nativeElement.height = this.height;
|
|
82
|
+
this.canvas.nativeElement.width = this.width();
|
|
83
|
+
this.canvas.nativeElement.height = this.height();
|
|
73
84
|
const context = this.canvas.nativeElement.getContext("2d");
|
|
74
85
|
if (!context) {
|
|
75
86
|
console.error("Failed to get 2D context");
|
|
@@ -81,9 +92,9 @@ class EasyImageDrawing {
|
|
|
81
92
|
this.context.lineCap = "round";
|
|
82
93
|
// set src to image
|
|
83
94
|
const image = new Image();
|
|
84
|
-
image.src = this.src;
|
|
95
|
+
image.src = this.src();
|
|
85
96
|
image.onload = () => {
|
|
86
|
-
this.context.drawImage(image, 0, 0, this.width, this.height);
|
|
97
|
+
this.context.drawImage(image, 0, 0, this.width(), this.height());
|
|
87
98
|
};
|
|
88
99
|
}
|
|
89
100
|
_setMouseEvents() {
|
|
@@ -127,29 +138,13 @@ class EasyImageDrawing {
|
|
|
127
138
|
ngOnDestroy() {
|
|
128
139
|
this.eventListeners.forEach((unlisten) => unlisten());
|
|
129
140
|
}
|
|
130
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
131
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
141
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: EasyImageDrawing, deps: [{ token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
142
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.18", type: EasyImageDrawing, isStandalone: true, selector: "easy-image-drawing", inputs: { width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, saveButtonColor: { classPropertyName: "saveButtonColor", publicName: "saveButtonColor", isSignal: true, isRequired: false, transformFunction: null }, undoButtonColor: { classPropertyName: "undoButtonColor", publicName: "undoButtonColor", isSignal: true, isRequired: false, transformFunction: null }, showColorPicker: { classPropertyName: "showColorPicker", publicName: "showColorPicker", isSignal: true, isRequired: false, transformFunction: null }, showlineWidthPicker: { classPropertyName: "showlineWidthPicker", publicName: "showlineWidthPicker", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { savedImage: "savedImage" }, viewQueries: [{ propertyName: "canvas", first: true, predicate: ["drawingCanvas"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"canvas-wrapper\">\r\n <canvas id=\"canvas\" #drawingCanvas></canvas>\r\n</div>\r\n<div class=\"image-button-wrapper\">\r\n <button\r\n type=\"button\"\r\n (click)=\"save()\"\r\n class=\"button save\"\r\n [style.background-color]=\"saveButtonColor()\"\r\n >\r\n Save\r\n </button>\r\n <button\r\n type=\"button\"\r\n (click)=\"clear()\"\r\n class=\"button undo\"\r\n [style.background-color]=\"undoButtonColor()\"\r\n >\r\n Undo\r\n </button>\r\n</div>\r\n<!-- color picker -->\r\n@if(showColorPicker()){\r\n<div class=\"color-picker-wrapper\">\r\n <button\r\n class=\"color-picker\"\r\n id=\"black\"\r\n (click)=\"onColorSelected('black')\"\r\n ></button>\r\n <button\r\n class=\"color-picker\"\r\n id=\"red\"\r\n (click)=\"onColorSelected('red')\"\r\n ></button>\r\n <button\r\n class=\"color-picker\"\r\n id=\"green\"\r\n (click)=\"onColorSelected('green')\"\r\n ></button>\r\n <button\r\n class=\"color-picker\"\r\n id=\"blue\"\r\n (click)=\"onColorSelected('blue')\"\r\n ></button>\r\n <button\r\n class=\"color-picker\"\r\n id=\"yellow\"\r\n (click)=\"onColorSelected('yellow')\"\r\n ></button>\r\n</div>\r\n}\r\n<!-- line width picker -->\r\n@if(showlineWidthPicker()){\r\n<div class=\"line-width-slider\">\r\n <input\r\n type=\"range\"\r\n min=\"5\"\r\n max=\"20\"\r\n value=\"5\"\r\n (input)=\"onLineWidthChanged($event)\"\r\n />\r\n</div>\r\n}\r\n", styles: ["@media only screen and (max-width: 900px){:host{display:flex;flex-direction:column;height:100%;width:100%}}.image-button-wrapper{display:flex;justify-content:center;margin:0 10px 10px 0}#canvas{border:1px solid #ccc;cursor:crosshair;max-width:100%;max-height:100%}.canvas-wrapper{display:flex;align-items:center;justify-content:center}.button-wrapper{display:flex;justify-content:center;margin-top:10px}button{margin:1rem;border:none;border-radius:5px;color:#fff;padding:.5rem 1rem;text-align:center;text-decoration:none;display:inline-block;font-size:16px;cursor:pointer}.color-picker-wrapper,.line-width-slider{display:flex;justify-content:center;margin:10px 0}.color-picker{margin:0 5px}#black{background-color:#000}#red{background-color:red}#green{background-color:green}#blue{background-color:#00f}#yellow{background-color:#ff0}\n"], dependencies: [{ kind: "ngmodule", type: MatSliderModule }] }); }
|
|
132
143
|
}
|
|
133
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
144
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: EasyImageDrawing, decorators: [{
|
|
134
145
|
type: Component,
|
|
135
|
-
args: [{ selector: "easy-image-drawing",
|
|
136
|
-
}], ctorParameters: () => [{ type: i0.Renderer2 }], propDecorators: {
|
|
137
|
-
type: Input
|
|
138
|
-
}], height: [{
|
|
139
|
-
type: Input
|
|
140
|
-
}], lineWidth: [{
|
|
141
|
-
type: Input
|
|
142
|
-
}], lineColor: [{
|
|
143
|
-
type: Input
|
|
144
|
-
}], src: [{
|
|
145
|
-
type: Input
|
|
146
|
-
}], saveButtonColor: [{
|
|
147
|
-
type: Input
|
|
148
|
-
}], undoButtonColor: [{
|
|
149
|
-
type: Input
|
|
150
|
-
}], savedImage: [{
|
|
151
|
-
type: Output
|
|
152
|
-
}], canvas: [{
|
|
146
|
+
args: [{ selector: "easy-image-drawing", imports: [MatSliderModule], template: "<div class=\"canvas-wrapper\">\r\n <canvas id=\"canvas\" #drawingCanvas></canvas>\r\n</div>\r\n<div class=\"image-button-wrapper\">\r\n <button\r\n type=\"button\"\r\n (click)=\"save()\"\r\n class=\"button save\"\r\n [style.background-color]=\"saveButtonColor()\"\r\n >\r\n Save\r\n </button>\r\n <button\r\n type=\"button\"\r\n (click)=\"clear()\"\r\n class=\"button undo\"\r\n [style.background-color]=\"undoButtonColor()\"\r\n >\r\n Undo\r\n </button>\r\n</div>\r\n<!-- color picker -->\r\n@if(showColorPicker()){\r\n<div class=\"color-picker-wrapper\">\r\n <button\r\n class=\"color-picker\"\r\n id=\"black\"\r\n (click)=\"onColorSelected('black')\"\r\n ></button>\r\n <button\r\n class=\"color-picker\"\r\n id=\"red\"\r\n (click)=\"onColorSelected('red')\"\r\n ></button>\r\n <button\r\n class=\"color-picker\"\r\n id=\"green\"\r\n (click)=\"onColorSelected('green')\"\r\n ></button>\r\n <button\r\n class=\"color-picker\"\r\n id=\"blue\"\r\n (click)=\"onColorSelected('blue')\"\r\n ></button>\r\n <button\r\n class=\"color-picker\"\r\n id=\"yellow\"\r\n (click)=\"onColorSelected('yellow')\"\r\n ></button>\r\n</div>\r\n}\r\n<!-- line width picker -->\r\n@if(showlineWidthPicker()){\r\n<div class=\"line-width-slider\">\r\n <input\r\n type=\"range\"\r\n min=\"5\"\r\n max=\"20\"\r\n value=\"5\"\r\n (input)=\"onLineWidthChanged($event)\"\r\n />\r\n</div>\r\n}\r\n", styles: ["@media only screen and (max-width: 900px){:host{display:flex;flex-direction:column;height:100%;width:100%}}.image-button-wrapper{display:flex;justify-content:center;margin:0 10px 10px 0}#canvas{border:1px solid #ccc;cursor:crosshair;max-width:100%;max-height:100%}.canvas-wrapper{display:flex;align-items:center;justify-content:center}.button-wrapper{display:flex;justify-content:center;margin-top:10px}button{margin:1rem;border:none;border-radius:5px;color:#fff;padding:.5rem 1rem;text-align:center;text-decoration:none;display:inline-block;font-size:16px;cursor:pointer}.color-picker-wrapper,.line-width-slider{display:flex;justify-content:center;margin:10px 0}.color-picker{margin:0 5px}#black{background-color:#000}#red{background-color:red}#green{background-color:green}#blue{background-color:#00f}#yellow{background-color:#ff0}\n"] }]
|
|
147
|
+
}], ctorParameters: () => [{ type: i0.Renderer2 }], propDecorators: { canvas: [{
|
|
153
148
|
type: ViewChild,
|
|
154
149
|
args: ["drawingCanvas"]
|
|
155
150
|
}] } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngx-easy-image-drawing.mjs","sources":["../../../projects/ngx-easy-image-drawing/src/lib/easy-image-drawing.component.ts","../../../projects/ngx-easy-image-drawing/src/lib/easy-image-drawing.component.html","../../../projects/ngx-easy-image-drawing/src/public-api.ts","../../../projects/ngx-easy-image-drawing/src/ngx-easy-image-drawing.ts"],"sourcesContent":["import {\r\n Component,\r\n ViewChild,\r\n ElementRef,\r\n AfterViewInit,\r\n Input,\r\n Output,\r\n EventEmitter,\r\n OnDestroy,\r\n OnChanges,\r\n Renderer2,\r\n SimpleChanges,\r\n} from \"@angular/core\";\r\n\r\n@Component({\r\n selector: \"easy-image-drawing\",\r\n standalone: true,\r\n imports: [],\r\n templateUrl: \"./easy-image-drawing.component.html\",\r\n styleUrls: [\"./easy-image-drawing.component.scss\"],\r\n})\r\nexport class EasyImageDrawing implements OnChanges, AfterViewInit, OnDestroy {\r\n @Input() width: number = 500;\r\n @Input() height: number = 500;\r\n @Input() lineWidth: number = 7;\r\n @Input() lineColor = \"#000000\";\r\n @Input() src = \"\";\r\n @Input() saveButtonColor = \"#4caf50\";\r\n @Input() undoButtonColor = \"#f44336\";\r\n @Output() savedImage = new EventEmitter<File>();\r\n\r\n // its important myCanvas matches the variable name in the template\r\n @ViewChild(\"drawingCanvas\") canvas!: ElementRef<HTMLCanvasElement>;\r\n\r\n context!: CanvasRenderingContext2D;\r\n private previousPosition: { x: number; y: number } = { x: 0, y: 0 };\r\n private activePath = false;\r\n private eventListeners: (() => void)[] = [];\r\n\r\n constructor(private renderer: Renderer2) {}\r\n\r\n ngAfterViewInit(): void {\r\n this._setCanvas();\r\n this._setMouseEvents();\r\n this._setMouseEventsMobile();\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (changes[\"src\"] && !changes[\"src\"].firstChange) {\r\n this.clear();\r\n }\r\n }\r\n public save(): void {\r\n const dataUrl = this.canvas.nativeElement.toDataURL(\"image/png\");\r\n const blob = this._dataURItoBlob(dataUrl);\r\n this.savedImage.next(new File([blob], \"image.png\"));\r\n }\r\n\r\n public clear(): void {\r\n this.context.clearRect(0, 0, this.width, this.height);\r\n const image = new Image();\r\n image.src = this.src;\r\n image.onload = () => {\r\n this.context.drawImage(image, 0, 0, this.width, this.height);\r\n };\r\n }\r\n\r\n private _dataURItoBlob(dataUrl: string) {\r\n const byteString = atob(dataUrl.split(\",\")[1]);\r\n const mimeString = dataUrl.split(\",\")[0].split(\":\")[1].split(\";\")[0];\r\n const ab = new ArrayBuffer(byteString.length);\r\n const dw = new DataView(ab);\r\n for (let i = 0; i < byteString.length; i++) {\r\n dw.setUint8(i, byteString.charCodeAt(i));\r\n }\r\n return new Blob([ab], { type: mimeString });\r\n }\r\n\r\n private _drawLine(event: MouseEvent | Touch): void {\r\n const currentPosition = this.getPosition(event.clientX, event.clientY);\r\n this.context.moveTo(this.previousPosition.x, this.previousPosition.y);\r\n this.context.lineTo(currentPosition.x, currentPosition.y);\r\n this.previousPosition = currentPosition;\r\n this.context.stroke();\r\n }\r\n\r\n private getPosition(\r\n clientX: number,\r\n clientY: number\r\n ): { x: number; y: number } {\r\n const rect = this.canvas.nativeElement.getBoundingClientRect();\r\n const scaleX = this.canvas.nativeElement.width / rect.width;\r\n const scaleY = this.canvas.nativeElement.height / rect.height;\r\n return {\r\n x: (clientX - rect.left) * scaleX,\r\n y: (clientY - rect.top) * scaleY,\r\n };\r\n }\r\n\r\n private _setCanvas(): void {\r\n if (!this.canvas) return;\r\n\r\n this.canvas.nativeElement.width = this.width;\r\n this.canvas.nativeElement.height = this.height;\r\n\r\n const context = this.canvas.nativeElement.getContext(\"2d\");\r\n if (!context) {\r\n console.error(\"Failed to get 2D context\");\r\n return;\r\n }\r\n this.context = context;\r\n this.context.lineWidth = this.lineWidth;\r\n this.context.strokeStyle = this.lineColor;\r\n this.context.lineCap = \"round\";\r\n\r\n // set src to image\r\n const image = new Image();\r\n image.src = this.src;\r\n image.onload = () => {\r\n this.context.drawImage(image, 0, 0, this.width, this.height);\r\n };\r\n }\r\n\r\n private _setMouseEvents(): void {\r\n this.eventListeners.push(\r\n this.renderer.listen(\"window\", \"mousedown\", this._onMouseDown.bind(this)),\r\n this.renderer.listen(\"window\", \"mousemove\", this._onMouseMove.bind(this)),\r\n this.renderer.listen(\"window\", \"mouseup\", this._onMouseUp.bind(this))\r\n );\r\n }\r\n\r\n private _onMouseDown(event: MouseEvent): void {\r\n this.activePath = true;\r\n this.context.beginPath();\r\n this.previousPosition = this.getPosition(event.clientX, event.clientY);\r\n }\r\n\r\n private _onMouseMove(event: MouseEvent): void {\r\n if (this.activePath) {\r\n this._drawLine(event);\r\n }\r\n }\r\n\r\n private _onMouseUp(): void {\r\n if (this.activePath) {\r\n this.context.closePath();\r\n this.activePath = false;\r\n }\r\n }\r\n\r\n private _setMouseEventsMobile(): void {\r\n this.eventListeners.push(\r\n this.renderer.listen(\r\n \"window\",\r\n \"touchstart\",\r\n this._onTouchStart.bind(this)\r\n ),\r\n this.renderer.listen(\"window\", \"touchmove\", this._onTouchMove.bind(this)),\r\n this.renderer.listen(\"window\", \"touchend\", this._onTouchEnd.bind(this))\r\n );\r\n }\r\n\r\n private _onTouchStart(event: TouchEvent): void {\r\n this.activePath = true;\r\n this.context.beginPath();\r\n this.previousPosition = this.getPosition(\r\n event.touches[0].clientX,\r\n event.touches[0].clientY\r\n );\r\n }\r\n\r\n private _onTouchMove(event: TouchEvent): void {\r\n if (this.activePath) {\r\n this._drawLine(event.touches[0]);\r\n }\r\n }\r\n\r\n private _onTouchEnd(): void {\r\n if (this.activePath) {\r\n this.context.closePath();\r\n this.activePath = false;\r\n }\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.eventListeners.forEach((unlisten) => unlisten());\r\n }\r\n}\r\n","<div class=\"canvas-wrapper\">\r\n <canvas id=\"canvas\" #drawingCanvas></canvas>\r\n</div>\r\n<div class=\"image-button-wrapper\">\r\n <button\r\n type=\"button\"\r\n (click)=\"save()\"\r\n class=\"button save\"\r\n [style.background-color]=\"saveButtonColor\"\r\n >\r\n Save\r\n </button>\r\n <button\r\n type=\"button\"\r\n (click)=\"clear()\"\r\n class=\"button undo\"\r\n [style.background-color]=\"undoButtonColor\"\r\n >\r\n Undo\r\n </button>\r\n</div>\r\n","/*\r\n * Public API Surface of ngx-easy-image-drawing\r\n */\r\n\r\nexport * from \"./lib/easy-image-drawing.component\";\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngx-easy-image-drawing.mjs","sources":["../../../projects/ngx-easy-image-drawing/src/lib/easy-image-drawing.component.ts","../../../projects/ngx-easy-image-drawing/src/lib/easy-image-drawing.component.html","../../../projects/ngx-easy-image-drawing/src/public-api.ts","../../../projects/ngx-easy-image-drawing/src/ngx-easy-image-drawing.ts"],"sourcesContent":["import {\r\n Component,\r\n ViewChild,\r\n ElementRef,\r\n AfterViewInit,\r\n OnDestroy,\r\n OnChanges,\r\n Renderer2,\r\n SimpleChanges,\r\n output,\r\n input,\r\n} from \"@angular/core\";\r\nimport { MatSliderModule } from \"@angular/material/slider\";\r\n\r\n@Component({\n selector: \"easy-image-drawing\",\n imports: [MatSliderModule],\n templateUrl: \"./easy-image-drawing.component.html\",\n styleUrls: [\"./easy-image-drawing.component.scss\"]\n})\r\nexport class EasyImageDrawing implements OnChanges, AfterViewInit, OnDestroy {\r\n width = input<number>(500);\r\n height = input<number>(500);\r\n src = input<string>(\"\");\r\n saveButtonColor = input<string>(\"#4caf50\");\r\n undoButtonColor = input<string>(\"#f44336\");\r\n showColorPicker = input<boolean>(true);\r\n showlineWidthPicker = input<boolean>(true);\r\n savedImage = output<File>();\r\n\r\n // its important myCanvas matches the variable name in the template\r\n @ViewChild(\"drawingCanvas\") canvas!: ElementRef<HTMLCanvasElement>;\r\n\r\n context!: CanvasRenderingContext2D;\r\n\r\n private lineWidth = 5;\r\n private lineColor = \"black\";\r\n private previousPosition: { x: number; y: number } = { x: 0, y: 0 };\r\n private activePath = false;\r\n private eventListeners: (() => void)[] = [];\r\n\r\n constructor(private renderer: Renderer2) {}\r\n\r\n ngAfterViewInit(): void {\r\n this._setCanvas();\r\n this._setMouseEvents();\r\n this._setMouseEventsMobile();\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (changes[\"src\"] && !changes[\"src\"].firstChange) {\r\n this.clear();\r\n }\r\n }\r\n public save(): void {\r\n const dataUrl = this.canvas.nativeElement.toDataURL(\"image/png\");\r\n const blob = this._dataURItoBlob(dataUrl);\r\n this.savedImage.emit(new File([blob], \"image.png\"));\r\n }\r\n\r\n public clear(): void {\r\n this.context.clearRect(0, 0, this.width(), this.height());\r\n const image = new Image();\r\n image.src = this.src();\r\n image.onload = () => {\r\n this.context.drawImage(image, 0, 0, this.width(), this.height());\r\n };\r\n }\r\n\r\n public onColorSelected(color: string): void {\r\n this.context.strokeStyle = color;\r\n }\r\n\r\n public onLineWidthChanged(event: any): void {\r\n if (event?.target?.value) {\r\n this.context.lineWidth = event.target.value;\r\n }\r\n }\r\n\r\n private _dataURItoBlob(dataUrl: string) {\r\n const byteString = atob(dataUrl.split(\",\")[1]);\r\n const mimeString = dataUrl.split(\",\")[0].split(\":\")[1].split(\";\")[0];\r\n const ab = new ArrayBuffer(byteString.length);\r\n const dw = new DataView(ab);\r\n for (let i = 0; i < byteString.length; i++) {\r\n dw.setUint8(i, byteString.charCodeAt(i));\r\n }\r\n return new Blob([ab], { type: mimeString });\r\n }\r\n\r\n private _drawLine(event: MouseEvent | Touch): void {\r\n const currentPosition = this.getPosition(event.clientX, event.clientY);\r\n this.context.moveTo(this.previousPosition.x, this.previousPosition.y);\r\n this.context.lineTo(currentPosition.x, currentPosition.y);\r\n this.previousPosition = currentPosition;\r\n this.context.stroke();\r\n }\r\n\r\n private getPosition(\r\n clientX: number,\r\n clientY: number\r\n ): { x: number; y: number } {\r\n const rect = this.canvas.nativeElement.getBoundingClientRect();\r\n const scaleX = this.canvas.nativeElement.width / rect.width;\r\n const scaleY = this.canvas.nativeElement.height / rect.height;\r\n return {\r\n x: (clientX - rect.left) * scaleX,\r\n y: (clientY - rect.top) * scaleY,\r\n };\r\n }\r\n\r\n private _setCanvas(): void {\r\n if (!this.canvas) return;\r\n\r\n this.canvas.nativeElement.width = this.width();\r\n this.canvas.nativeElement.height = this.height();\r\n\r\n const context = this.canvas.nativeElement.getContext(\"2d\");\r\n if (!context) {\r\n console.error(\"Failed to get 2D context\");\r\n return;\r\n }\r\n this.context = context;\r\n this.context.lineWidth = this.lineWidth;\r\n this.context.strokeStyle = this.lineColor;\r\n this.context.lineCap = \"round\";\r\n\r\n // set src to image\r\n const image = new Image();\r\n image.src = this.src();\r\n image.onload = () => {\r\n this.context.drawImage(image, 0, 0, this.width(), this.height());\r\n };\r\n }\r\n\r\n private _setMouseEvents(): void {\r\n this.eventListeners.push(\r\n this.renderer.listen(\"window\", \"mousedown\", this._onMouseDown.bind(this)),\r\n this.renderer.listen(\"window\", \"mousemove\", this._onMouseMove.bind(this)),\r\n this.renderer.listen(\"window\", \"mouseup\", this._onMouseUp.bind(this))\r\n );\r\n }\r\n\r\n private _onMouseDown(event: MouseEvent): void {\r\n this.activePath = true;\r\n this.context.beginPath();\r\n this.previousPosition = this.getPosition(event.clientX, event.clientY);\r\n }\r\n\r\n private _onMouseMove(event: MouseEvent): void {\r\n if (this.activePath) {\r\n this._drawLine(event);\r\n }\r\n }\r\n\r\n private _onMouseUp(): void {\r\n if (this.activePath) {\r\n this.context.closePath();\r\n this.activePath = false;\r\n }\r\n }\r\n\r\n private _setMouseEventsMobile(): void {\r\n this.eventListeners.push(\r\n this.renderer.listen(\r\n \"window\",\r\n \"touchstart\",\r\n this._onTouchStart.bind(this)\r\n ),\r\n this.renderer.listen(\"window\", \"touchmove\", this._onTouchMove.bind(this)),\r\n this.renderer.listen(\"window\", \"touchend\", this._onTouchEnd.bind(this))\r\n );\r\n }\r\n\r\n private _onTouchStart(event: TouchEvent): void {\r\n this.activePath = true;\r\n this.context.beginPath();\r\n this.previousPosition = this.getPosition(\r\n event.touches[0].clientX,\r\n event.touches[0].clientY\r\n );\r\n }\r\n\r\n private _onTouchMove(event: TouchEvent): void {\r\n if (this.activePath) {\r\n this._drawLine(event.touches[0]);\r\n }\r\n }\r\n\r\n private _onTouchEnd(): void {\r\n if (this.activePath) {\r\n this.context.closePath();\r\n this.activePath = false;\r\n }\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.eventListeners.forEach((unlisten) => unlisten());\r\n }\r\n}\r\n","<div class=\"canvas-wrapper\">\r\n <canvas id=\"canvas\" #drawingCanvas></canvas>\r\n</div>\r\n<div class=\"image-button-wrapper\">\r\n <button\r\n type=\"button\"\r\n (click)=\"save()\"\r\n class=\"button save\"\r\n [style.background-color]=\"saveButtonColor()\"\r\n >\r\n Save\r\n </button>\r\n <button\r\n type=\"button\"\r\n (click)=\"clear()\"\r\n class=\"button undo\"\r\n [style.background-color]=\"undoButtonColor()\"\r\n >\r\n Undo\r\n </button>\r\n</div>\r\n<!-- color picker -->\r\n@if(showColorPicker()){\r\n<div class=\"color-picker-wrapper\">\r\n <button\r\n class=\"color-picker\"\r\n id=\"black\"\r\n (click)=\"onColorSelected('black')\"\r\n ></button>\r\n <button\r\n class=\"color-picker\"\r\n id=\"red\"\r\n (click)=\"onColorSelected('red')\"\r\n ></button>\r\n <button\r\n class=\"color-picker\"\r\n id=\"green\"\r\n (click)=\"onColorSelected('green')\"\r\n ></button>\r\n <button\r\n class=\"color-picker\"\r\n id=\"blue\"\r\n (click)=\"onColorSelected('blue')\"\r\n ></button>\r\n <button\r\n class=\"color-picker\"\r\n id=\"yellow\"\r\n (click)=\"onColorSelected('yellow')\"\r\n ></button>\r\n</div>\r\n}\r\n<!-- line width picker -->\r\n@if(showlineWidthPicker()){\r\n<div class=\"line-width-slider\">\r\n <input\r\n type=\"range\"\r\n min=\"5\"\r\n max=\"20\"\r\n value=\"5\"\r\n (input)=\"onLineWidthChanged($event)\"\r\n />\r\n</div>\r\n}\r\n","/*\r\n * Public API Surface of ngx-easy-image-drawing\r\n */\r\n\r\nexport * from \"./lib/easy-image-drawing.component\";\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
import { ElementRef, AfterViewInit,
|
|
1
|
+
import { ElementRef, AfterViewInit, OnDestroy, OnChanges, Renderer2, SimpleChanges } from "@angular/core";
|
|
2
2
|
import * as i0 from "@angular/core";
|
|
3
3
|
export declare class EasyImageDrawing implements OnChanges, AfterViewInit, OnDestroy {
|
|
4
4
|
private renderer;
|
|
5
|
-
width: number
|
|
6
|
-
height: number
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
savedImage:
|
|
5
|
+
width: import("@angular/core").InputSignal<number>;
|
|
6
|
+
height: import("@angular/core").InputSignal<number>;
|
|
7
|
+
src: import("@angular/core").InputSignal<string>;
|
|
8
|
+
saveButtonColor: import("@angular/core").InputSignal<string>;
|
|
9
|
+
undoButtonColor: import("@angular/core").InputSignal<string>;
|
|
10
|
+
showColorPicker: import("@angular/core").InputSignal<boolean>;
|
|
11
|
+
showlineWidthPicker: import("@angular/core").InputSignal<boolean>;
|
|
12
|
+
savedImage: import("@angular/core").OutputEmitterRef<File>;
|
|
13
13
|
canvas: ElementRef<HTMLCanvasElement>;
|
|
14
14
|
context: CanvasRenderingContext2D;
|
|
15
|
+
private lineWidth;
|
|
16
|
+
private lineColor;
|
|
15
17
|
private previousPosition;
|
|
16
18
|
private activePath;
|
|
17
19
|
private eventListeners;
|
|
@@ -20,6 +22,8 @@ export declare class EasyImageDrawing implements OnChanges, AfterViewInit, OnDes
|
|
|
20
22
|
ngOnChanges(changes: SimpleChanges): void;
|
|
21
23
|
save(): void;
|
|
22
24
|
clear(): void;
|
|
25
|
+
onColorSelected(color: string): void;
|
|
26
|
+
onLineWidthChanged(event: any): void;
|
|
23
27
|
private _dataURItoBlob;
|
|
24
28
|
private _drawLine;
|
|
25
29
|
private getPosition;
|
|
@@ -34,5 +38,5 @@ export declare class EasyImageDrawing implements OnChanges, AfterViewInit, OnDes
|
|
|
34
38
|
private _onTouchEnd;
|
|
35
39
|
ngOnDestroy(): void;
|
|
36
40
|
static ɵfac: i0.ɵɵFactoryDeclaration<EasyImageDrawing, never>;
|
|
37
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<EasyImageDrawing, "easy-image-drawing", never, { "width": { "alias": "width"; "required": false; }; "height": { "alias": "height"; "required": false; }; "
|
|
41
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<EasyImageDrawing, "easy-image-drawing", never, { "width": { "alias": "width"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; "src": { "alias": "src"; "required": false; "isSignal": true; }; "saveButtonColor": { "alias": "saveButtonColor"; "required": false; "isSignal": true; }; "undoButtonColor": { "alias": "undoButtonColor"; "required": false; "isSignal": true; }; "showColorPicker": { "alias": "showColorPicker"; "required": false; "isSignal": true; }; "showlineWidthPicker": { "alias": "showlineWidthPicker"; "required": false; "isSignal": true; }; }, { "savedImage": "savedImage"; }, never, never, true, never>;
|
|
38
42
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ngx-easy-image-drawing",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.30",
|
|
4
4
|
"author": "Alex Voronin <alex.varonin@gmail.com>",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"peerDependencies": {
|
|
7
|
-
"@angular/common": "^
|
|
8
|
-
"@angular/core": "^
|
|
7
|
+
"@angular/common": "^19.0.0",
|
|
8
|
+
"@angular/core": "^19.0.0"
|
|
9
9
|
},
|
|
10
10
|
"description": "Angular library for easy image drawing on canvas",
|
|
11
11
|
"dependencies": {
|
|
@@ -31,8 +31,6 @@
|
|
|
31
31
|
},
|
|
32
32
|
".": {
|
|
33
33
|
"types": "./index.d.ts",
|
|
34
|
-
"esm2022": "./esm2022/ngx-easy-image-drawing.mjs",
|
|
35
|
-
"esm": "./esm2022/ngx-easy-image-drawing.mjs",
|
|
36
34
|
"default": "./fesm2022/ngx-easy-image-drawing.mjs"
|
|
37
35
|
}
|
|
38
36
|
}
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import { Component, ViewChild, Input, Output, EventEmitter, } from "@angular/core";
|
|
2
|
-
import * as i0 from "@angular/core";
|
|
3
|
-
export class EasyImageDrawing {
|
|
4
|
-
constructor(renderer) {
|
|
5
|
-
this.renderer = renderer;
|
|
6
|
-
this.width = 500;
|
|
7
|
-
this.height = 500;
|
|
8
|
-
this.lineWidth = 7;
|
|
9
|
-
this.lineColor = "#000000";
|
|
10
|
-
this.src = "";
|
|
11
|
-
this.saveButtonColor = "#4caf50";
|
|
12
|
-
this.undoButtonColor = "#f44336";
|
|
13
|
-
this.savedImage = new EventEmitter();
|
|
14
|
-
this.previousPosition = { x: 0, y: 0 };
|
|
15
|
-
this.activePath = false;
|
|
16
|
-
this.eventListeners = [];
|
|
17
|
-
}
|
|
18
|
-
ngAfterViewInit() {
|
|
19
|
-
this._setCanvas();
|
|
20
|
-
this._setMouseEvents();
|
|
21
|
-
this._setMouseEventsMobile();
|
|
22
|
-
}
|
|
23
|
-
ngOnChanges(changes) {
|
|
24
|
-
if (changes["src"] && !changes["src"].firstChange) {
|
|
25
|
-
this.clear();
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
save() {
|
|
29
|
-
const dataUrl = this.canvas.nativeElement.toDataURL("image/png");
|
|
30
|
-
const blob = this._dataURItoBlob(dataUrl);
|
|
31
|
-
this.savedImage.next(new File([blob], "image.png"));
|
|
32
|
-
}
|
|
33
|
-
clear() {
|
|
34
|
-
this.context.clearRect(0, 0, this.width, this.height);
|
|
35
|
-
const image = new Image();
|
|
36
|
-
image.src = this.src;
|
|
37
|
-
image.onload = () => {
|
|
38
|
-
this.context.drawImage(image, 0, 0, this.width, this.height);
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
_dataURItoBlob(dataUrl) {
|
|
42
|
-
const byteString = atob(dataUrl.split(",")[1]);
|
|
43
|
-
const mimeString = dataUrl.split(",")[0].split(":")[1].split(";")[0];
|
|
44
|
-
const ab = new ArrayBuffer(byteString.length);
|
|
45
|
-
const dw = new DataView(ab);
|
|
46
|
-
for (let i = 0; i < byteString.length; i++) {
|
|
47
|
-
dw.setUint8(i, byteString.charCodeAt(i));
|
|
48
|
-
}
|
|
49
|
-
return new Blob([ab], { type: mimeString });
|
|
50
|
-
}
|
|
51
|
-
_drawLine(event) {
|
|
52
|
-
const currentPosition = this.getPosition(event.clientX, event.clientY);
|
|
53
|
-
this.context.moveTo(this.previousPosition.x, this.previousPosition.y);
|
|
54
|
-
this.context.lineTo(currentPosition.x, currentPosition.y);
|
|
55
|
-
this.previousPosition = currentPosition;
|
|
56
|
-
this.context.stroke();
|
|
57
|
-
}
|
|
58
|
-
getPosition(clientX, clientY) {
|
|
59
|
-
const rect = this.canvas.nativeElement.getBoundingClientRect();
|
|
60
|
-
const scaleX = this.canvas.nativeElement.width / rect.width;
|
|
61
|
-
const scaleY = this.canvas.nativeElement.height / rect.height;
|
|
62
|
-
return {
|
|
63
|
-
x: (clientX - rect.left) * scaleX,
|
|
64
|
-
y: (clientY - rect.top) * scaleY,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
_setCanvas() {
|
|
68
|
-
if (!this.canvas)
|
|
69
|
-
return;
|
|
70
|
-
this.canvas.nativeElement.width = this.width;
|
|
71
|
-
this.canvas.nativeElement.height = this.height;
|
|
72
|
-
const context = this.canvas.nativeElement.getContext("2d");
|
|
73
|
-
if (!context) {
|
|
74
|
-
console.error("Failed to get 2D context");
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
this.context = context;
|
|
78
|
-
this.context.lineWidth = this.lineWidth;
|
|
79
|
-
this.context.strokeStyle = this.lineColor;
|
|
80
|
-
this.context.lineCap = "round";
|
|
81
|
-
// set src to image
|
|
82
|
-
const image = new Image();
|
|
83
|
-
image.src = this.src;
|
|
84
|
-
image.onload = () => {
|
|
85
|
-
this.context.drawImage(image, 0, 0, this.width, this.height);
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
_setMouseEvents() {
|
|
89
|
-
this.eventListeners.push(this.renderer.listen("window", "mousedown", this._onMouseDown.bind(this)), this.renderer.listen("window", "mousemove", this._onMouseMove.bind(this)), this.renderer.listen("window", "mouseup", this._onMouseUp.bind(this)));
|
|
90
|
-
}
|
|
91
|
-
_onMouseDown(event) {
|
|
92
|
-
this.activePath = true;
|
|
93
|
-
this.context.beginPath();
|
|
94
|
-
this.previousPosition = this.getPosition(event.clientX, event.clientY);
|
|
95
|
-
}
|
|
96
|
-
_onMouseMove(event) {
|
|
97
|
-
if (this.activePath) {
|
|
98
|
-
this._drawLine(event);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
_onMouseUp() {
|
|
102
|
-
if (this.activePath) {
|
|
103
|
-
this.context.closePath();
|
|
104
|
-
this.activePath = false;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
_setMouseEventsMobile() {
|
|
108
|
-
this.eventListeners.push(this.renderer.listen("window", "touchstart", this._onTouchStart.bind(this)), this.renderer.listen("window", "touchmove", this._onTouchMove.bind(this)), this.renderer.listen("window", "touchend", this._onTouchEnd.bind(this)));
|
|
109
|
-
}
|
|
110
|
-
_onTouchStart(event) {
|
|
111
|
-
this.activePath = true;
|
|
112
|
-
this.context.beginPath();
|
|
113
|
-
this.previousPosition = this.getPosition(event.touches[0].clientX, event.touches[0].clientY);
|
|
114
|
-
}
|
|
115
|
-
_onTouchMove(event) {
|
|
116
|
-
if (this.activePath) {
|
|
117
|
-
this._drawLine(event.touches[0]);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
_onTouchEnd() {
|
|
121
|
-
if (this.activePath) {
|
|
122
|
-
this.context.closePath();
|
|
123
|
-
this.activePath = false;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
ngOnDestroy() {
|
|
127
|
-
this.eventListeners.forEach((unlisten) => unlisten());
|
|
128
|
-
}
|
|
129
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: EasyImageDrawing, deps: [{ token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
130
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.1.3", type: EasyImageDrawing, isStandalone: true, selector: "easy-image-drawing", inputs: { width: "width", height: "height", lineWidth: "lineWidth", lineColor: "lineColor", src: "src", saveButtonColor: "saveButtonColor", undoButtonColor: "undoButtonColor" }, outputs: { savedImage: "savedImage" }, viewQueries: [{ propertyName: "canvas", first: true, predicate: ["drawingCanvas"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"canvas-wrapper\">\r\n <canvas id=\"canvas\" #drawingCanvas></canvas>\r\n</div>\r\n<div class=\"image-button-wrapper\">\r\n <button\r\n type=\"button\"\r\n (click)=\"save()\"\r\n class=\"button save\"\r\n [style.background-color]=\"saveButtonColor\"\r\n >\r\n Save\r\n </button>\r\n <button\r\n type=\"button\"\r\n (click)=\"clear()\"\r\n class=\"button undo\"\r\n [style.background-color]=\"undoButtonColor\"\r\n >\r\n Undo\r\n </button>\r\n</div>\r\n", styles: ["@media only screen and (max-width: 900px){:host{display:flex;flex-direction:column;height:100%;width:100%}}.image-button-wrapper{display:flex;justify-content:center;margin:0 10px 10px 0}#canvas{border:1px solid #ccc;cursor:crosshair;max-width:100%;max-height:100%}.canvas-wrapper{display:flex;align-items:center;justify-content:center}.button-wrapper{display:flex;justify-content:center;margin-top:10px}button{margin:1rem;border:none;border-radius:5px;color:#fff;padding:.5rem 1rem;text-align:center;text-decoration:none;display:inline-block;font-size:16px;cursor:pointer}\n"] }); }
|
|
131
|
-
}
|
|
132
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: EasyImageDrawing, decorators: [{
|
|
133
|
-
type: Component,
|
|
134
|
-
args: [{ selector: "easy-image-drawing", standalone: true, imports: [], template: "<div class=\"canvas-wrapper\">\r\n <canvas id=\"canvas\" #drawingCanvas></canvas>\r\n</div>\r\n<div class=\"image-button-wrapper\">\r\n <button\r\n type=\"button\"\r\n (click)=\"save()\"\r\n class=\"button save\"\r\n [style.background-color]=\"saveButtonColor\"\r\n >\r\n Save\r\n </button>\r\n <button\r\n type=\"button\"\r\n (click)=\"clear()\"\r\n class=\"button undo\"\r\n [style.background-color]=\"undoButtonColor\"\r\n >\r\n Undo\r\n </button>\r\n</div>\r\n", styles: ["@media only screen and (max-width: 900px){:host{display:flex;flex-direction:column;height:100%;width:100%}}.image-button-wrapper{display:flex;justify-content:center;margin:0 10px 10px 0}#canvas{border:1px solid #ccc;cursor:crosshair;max-width:100%;max-height:100%}.canvas-wrapper{display:flex;align-items:center;justify-content:center}.button-wrapper{display:flex;justify-content:center;margin-top:10px}button{margin:1rem;border:none;border-radius:5px;color:#fff;padding:.5rem 1rem;text-align:center;text-decoration:none;display:inline-block;font-size:16px;cursor:pointer}\n"] }]
|
|
135
|
-
}], ctorParameters: () => [{ type: i0.Renderer2 }], propDecorators: { width: [{
|
|
136
|
-
type: Input
|
|
137
|
-
}], height: [{
|
|
138
|
-
type: Input
|
|
139
|
-
}], lineWidth: [{
|
|
140
|
-
type: Input
|
|
141
|
-
}], lineColor: [{
|
|
142
|
-
type: Input
|
|
143
|
-
}], src: [{
|
|
144
|
-
type: Input
|
|
145
|
-
}], saveButtonColor: [{
|
|
146
|
-
type: Input
|
|
147
|
-
}], undoButtonColor: [{
|
|
148
|
-
type: Input
|
|
149
|
-
}], savedImage: [{
|
|
150
|
-
type: Output
|
|
151
|
-
}], canvas: [{
|
|
152
|
-
type: ViewChild,
|
|
153
|
-
args: ["drawingCanvas"]
|
|
154
|
-
}] } });
|
|
155
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWFzeS1pbWFnZS1kcmF3aW5nLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1lYXN5LWltYWdlLWRyYXdpbmcvc3JjL2xpYi9lYXN5LWltYWdlLWRyYXdpbmcuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWVhc3ktaW1hZ2UtZHJhd2luZy9zcmMvbGliL2Vhc3ktaW1hZ2UtZHJhd2luZy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULFNBQVMsRUFHVCxLQUFLLEVBQ0wsTUFBTSxFQUNOLFlBQVksR0FLYixNQUFNLGVBQWUsQ0FBQzs7QUFTdkIsTUFBTSxPQUFPLGdCQUFnQjtJQWtCM0IsWUFBb0IsUUFBbUI7UUFBbkIsYUFBUSxHQUFSLFFBQVEsQ0FBVztRQWpCOUIsVUFBSyxHQUFXLEdBQUcsQ0FBQztRQUNwQixXQUFNLEdBQVcsR0FBRyxDQUFDO1FBQ3JCLGNBQVMsR0FBVyxDQUFDLENBQUM7UUFDdEIsY0FBUyxHQUFHLFNBQVMsQ0FBQztRQUN0QixRQUFHLEdBQUcsRUFBRSxDQUFDO1FBQ1Qsb0JBQWUsR0FBRyxTQUFTLENBQUM7UUFDNUIsb0JBQWUsR0FBRyxTQUFTLENBQUM7UUFDM0IsZUFBVSxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7UUFNeEMscUJBQWdCLEdBQTZCLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7UUFDNUQsZUFBVSxHQUFHLEtBQUssQ0FBQztRQUNuQixtQkFBYyxHQUFtQixFQUFFLENBQUM7SUFFRixDQUFDO0lBRTNDLGVBQWU7UUFDYixJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDbEIsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO0lBQy9CLENBQUM7SUFF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Q0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNwQixJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNuQyxDQUFDO0lBQ0gsQ0FBQztJQUVPLFdBQVc7UUFDakIsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDcEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztRQUMxQixDQUFDO0lBQ0gsQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztJQUN4RCxDQUFDOzhHQXJLVSxnQkFBZ0I7a0dBQWhCLGdCQUFnQixxYUNyQjdCLHVmQXFCQTs7MkZEQWEsZ0JBQWdCO2tCQVA1QixTQUFTOytCQUNFLG9CQUFvQixjQUNsQixJQUFJLFdBQ1AsRUFBRTs4RUFLRixLQUFLO3NCQUFiLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLO2dCQUNHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFDRyxHQUFHO3NCQUFYLEtBQUs7Z0JBQ0csZUFBZTtzQkFBdkIsS0FBSztnQkFDRyxlQUFlO3NCQUF2QixLQUFLO2dCQUNJLFVBQVU7c0JBQW5CLE1BQU07Z0JBR3FCLE1BQU07c0JBQWpDLFNBQVM7dUJBQUMsZUFBZSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgQ29tcG9uZW50LFxyXG4gIFZpZXdDaGlsZCxcclxuICBFbGVtZW50UmVmLFxyXG4gIEFmdGVyVmlld0luaXQsXHJcbiAgSW5wdXQsXHJcbiAgT3V0cHV0LFxyXG4gIEV2ZW50RW1pdHRlcixcclxuICBPbkRlc3Ryb3ksXHJcbiAgT25DaGFuZ2VzLFxyXG4gIFJlbmRlcmVyMixcclxuICBTaW1wbGVDaGFuZ2VzLFxyXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogXCJlYXN5LWltYWdlLWRyYXdpbmdcIixcclxuICBzdGFuZGFsb25lOiB0cnVlLFxyXG4gIGltcG9ydHM6IFtdLFxyXG4gIHRlbXBsYXRlVXJsOiBcIi4vZWFzeS1pbWFnZS1kcmF3aW5nLmNvbXBvbmVudC5odG1sXCIsXHJcbiAgc3R5bGVVcmxzOiBbXCIuL2Vhc3ktaW1hZ2UtZHJhd2luZy5jb21wb25lbnQuc2Nzc1wiXSxcclxufSlcclxuZXhwb3J0IGNsYXNzIEVhc3lJbWFnZURyYXdpbmcgaW1wbGVtZW50cyBPbkNoYW5nZXMsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XHJcbiAgQElucHV0KCkgd2lkdGg6IG51bWJlciA9IDUwMDtcclxuICBASW5wdXQoKSBoZWlnaHQ6IG51bWJlciA9IDUwMDtcclxuICBASW5wdXQoKSBsaW5lV2lkdGg6IG51bWJlciA9IDc7XHJcbiAgQElucHV0KCkgbGluZUNvbG9yID0gXCIjMDAwMDAwXCI7XHJcbiAgQElucHV0KCkgc3JjID0gXCJcIjtcclxuICBASW5wdXQoKSBzYXZlQnV0dG9uQ29sb3IgPSBcIiM0Y2FmNTBcIjtcclxuICBASW5wdXQoKSB1bmRvQnV0dG9uQ29sb3IgPSBcIiNmNDQzMzZcIjtcclxuICBAT3V0cHV0KCkgc2F2ZWRJbWFnZSA9IG5ldyBFdmVudEVtaXR0ZXI8RmlsZT4oKTtcclxuXHJcbiAgLy8gaXRzIGltcG9ydGFudCBteUNhbnZhcyBtYXRjaGVzIHRoZSB2YXJpYWJsZSBuYW1lIGluIHRoZSB0ZW1wbGF0ZVxyXG4gIEBWaWV3Q2hpbGQoXCJkcmF3aW5nQ2FudmFzXCIpIGNhbnZhcyE6IEVsZW1lbnRSZWY8SFRNTENhbnZhc0VsZW1lbnQ+O1xyXG5cclxuICBjb250ZXh0ITogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEO1xyXG4gIHByaXZhdGUgcHJldmlvdXNQb3NpdGlvbjogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9ID0geyB4OiAwLCB5OiAwIH07XHJcbiAgcHJpdmF0ZSBhY3RpdmVQYXRoID0gZmFsc2U7XHJcbiAgcHJpdmF0ZSBldmVudExpc3RlbmVyczogKCgpID0+IHZvaWQpW10gPSBbXTtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyKSB7fVxyXG5cclxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XHJcbiAgICB0aGlzLl9zZXRDYW52YXMoKTtcclxuICAgIHRoaXMuX3NldE1vdXNlRXZlbnRzKCk7XHJcbiAgICB0aGlzLl9zZXRNb3VzZUV2ZW50c01vYmlsZSgpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xyXG4gICAgaWYgKGNoYW5nZXNbXCJzcmNcIl0gJiYgIWNoYW5nZXNbXCJzcmNcIl0uZmlyc3RDaGFuZ2UpIHtcclxuICAgICAgdGhpcy5jbGVhcigpO1xyXG4gICAgfVxyXG4gIH1cclxuICBwdWJsaWMgc2F2ZSgpOiB2b2lkIHtcclxuICAgIGNvbnN0IGRhdGFVcmwgPSB0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50LnRvRGF0YVVSTChcImltYWdlL3BuZ1wiKTtcclxuICAgIGNvbnN0IGJsb2IgPSB0aGlzLl9kYXRhVVJJdG9CbG9iKGRhdGFVcmwpO1xyXG4gICAgdGhpcy5zYXZlZEltYWdlLm5leHQobmV3IEZpbGUoW2Jsb2JdLCBcImltYWdlLnBuZ1wiKSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgY2xlYXIoKTogdm9pZCB7XHJcbiAgICB0aGlzLmNvbnRleHQuY2xlYXJSZWN0KDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0KTtcclxuICAgIGNvbnN0IGltYWdlID0gbmV3IEltYWdlKCk7XHJcbiAgICBpbWFnZS5zcmMgPSB0aGlzLnNyYztcclxuICAgIGltYWdlLm9ubG9hZCA9ICgpID0+IHtcclxuICAgICAgdGhpcy5jb250ZXh0LmRyYXdJbWFnZShpbWFnZSwgMCwgMCwgdGhpcy53aWR0aCwgdGhpcy5oZWlnaHQpO1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgX2RhdGFVUkl0b0Jsb2IoZGF0YVVybDogc3RyaW5nKSB7XHJcbiAgICBjb25zdCBieXRlU3RyaW5nID0gYXRvYihkYXRhVXJsLnNwbGl0KFwiLFwiKVsxXSk7XHJcbiAgICBjb25zdCBtaW1lU3RyaW5nID0gZGF0YVVybC5zcGxpdChcIixcIilbMF0uc3BsaXQoXCI6XCIpWzFdLnNwbGl0KFwiO1wiKVswXTtcclxuICAgIGNvbnN0IGFiID0gbmV3IEFycmF5QnVmZmVyKGJ5dGVTdHJpbmcubGVuZ3RoKTtcclxuICAgIGNvbnN0IGR3ID0gbmV3IERhdGFWaWV3KGFiKTtcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYnl0ZVN0cmluZy5sZW5ndGg7IGkrKykge1xyXG4gICAgICBkdy5zZXRVaW50OChpLCBieXRlU3RyaW5nLmNoYXJDb2RlQXQoaSkpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG5ldyBCbG9iKFthYl0sIHsgdHlwZTogbWltZVN0cmluZyB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgX2RyYXdMaW5lKGV2ZW50OiBNb3VzZUV2ZW50IHwgVG91Y2gpOiB2b2lkIHtcclxuICAgIGNvbnN0IGN1cnJlbnRQb3NpdGlvbiA9IHRoaXMuZ2V0UG9zaXRpb24oZXZlbnQuY2xpZW50WCwgZXZlbnQuY2xpZW50WSk7XHJcbiAgICB0aGlzLmNvbnRleHQubW92ZVRvKHRoaXMucHJldmlvdXNQb3NpdGlvbi54LCB0aGlzLnByZXZpb3VzUG9zaXRpb24ueSk7XHJcbiAgICB0aGlzLmNvbnRleHQubGluZVRvKGN1cnJlbnRQb3NpdGlvbi54LCBjdXJyZW50UG9zaXRpb24ueSk7XHJcbiAgICB0aGlzLnByZXZpb3VzUG9zaXRpb24gPSBjdXJyZW50UG9zaXRpb247XHJcbiAgICB0aGlzLmNvbnRleHQuc3Ryb2tlKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdldFBvc2l0aW9uKFxyXG4gICAgY2xpZW50WDogbnVtYmVyLFxyXG4gICAgY2xpZW50WTogbnVtYmVyXHJcbiAgKTogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9IHtcclxuICAgIGNvbnN0IHJlY3QgPSB0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xyXG4gICAgY29uc3Qgc2NhbGVYID0gdGhpcy5jYW52YXMubmF0aXZlRWxlbWVudC53aWR0aCAvIHJlY3Qud2lkdGg7XHJcbiAgICBjb25zdCBzY2FsZVkgPSB0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50LmhlaWdodCAvIHJlY3QuaGVpZ2h0O1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgeDogKGNsaWVudFggLSByZWN0LmxlZnQpICogc2NhbGVYLFxyXG4gICAgICB5OiAoY2xpZW50WSAtIHJlY3QudG9wKSAqIHNjYWxlWSxcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF9zZXRDYW52YXMoKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuY2FudmFzKSByZXR1cm47XHJcblxyXG4gICAgdGhpcy5jYW52YXMubmF0aXZlRWxlbWVudC53aWR0aCA9IHRoaXMud2lkdGg7XHJcbiAgICB0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50LmhlaWdodCA9IHRoaXMuaGVpZ2h0O1xyXG5cclxuICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50LmdldENvbnRleHQoXCIyZFwiKTtcclxuICAgIGlmICghY29udGV4dCkge1xyXG4gICAgICBjb25zb2xlLmVycm9yKFwiRmFpbGVkIHRvIGdldCAyRCBjb250ZXh0XCIpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0aGlzLmNvbnRleHQgPSBjb250ZXh0O1xyXG4gICAgdGhpcy5jb250ZXh0LmxpbmVXaWR0aCA9IHRoaXMubGluZVdpZHRoO1xyXG4gICAgdGhpcy5jb250ZXh0LnN0cm9rZVN0eWxlID0gdGhpcy5saW5lQ29sb3I7XHJcbiAgICB0aGlzLmNvbnRleHQubGluZUNhcCA9IFwicm91bmRcIjtcclxuXHJcbiAgICAvLyBzZXQgc3JjIHRvIGltYWdlXHJcbiAgICBjb25zdCBpbWFnZSA9IG5ldyBJbWFnZSgpO1xyXG4gICAgaW1hZ2Uuc3JjID0gdGhpcy5zcmM7XHJcbiAgICBpbWFnZS5vbmxvYWQgPSAoKSA9PiB7XHJcbiAgICAgIHRoaXMuY29udGV4dC5kcmF3SW1hZ2UoaW1hZ2UsIDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0KTtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF9zZXRNb3VzZUV2ZW50cygpOiB2b2lkIHtcclxuICAgIHRoaXMuZXZlbnRMaXN0ZW5lcnMucHVzaChcclxuICAgICAgdGhpcy5yZW5kZXJlci5saXN0ZW4oXCJ3aW5kb3dcIiwgXCJtb3VzZWRvd25cIiwgdGhpcy5fb25Nb3VzZURvd24uYmluZCh0aGlzKSksXHJcbiAgICAgIHRoaXMucmVuZGVyZXIubGlzdGVuKFwid2luZG93XCIsIFwibW91c2Vtb3ZlXCIsIHRoaXMuX29uTW91c2VNb3ZlLmJpbmQodGhpcykpLFxyXG4gICAgICB0aGlzLnJlbmRlcmVyLmxpc3RlbihcIndpbmRvd1wiLCBcIm1vdXNldXBcIiwgdGhpcy5fb25Nb3VzZVVwLmJpbmQodGhpcykpXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfb25Nb3VzZURvd24oZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcclxuICAgIHRoaXMuYWN0aXZlUGF0aCA9IHRydWU7XHJcbiAgICB0aGlzLmNvbnRleHQuYmVnaW5QYXRoKCk7XHJcbiAgICB0aGlzLnByZXZpb3VzUG9zaXRpb24gPSB0aGlzLmdldFBvc2l0aW9uKGV2ZW50LmNsaWVudFgsIGV2ZW50LmNsaWVudFkpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfb25Nb3VzZU1vdmUoZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmFjdGl2ZVBhdGgpIHtcclxuICAgICAgdGhpcy5fZHJhd0xpbmUoZXZlbnQpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfb25Nb3VzZVVwKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuYWN0aXZlUGF0aCkge1xyXG4gICAgICB0aGlzLmNvbnRleHQuY2xvc2VQYXRoKCk7XHJcbiAgICAgIHRoaXMuYWN0aXZlUGF0aCA9IGZhbHNlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfc2V0TW91c2VFdmVudHNNb2JpbGUoKTogdm9pZCB7XHJcbiAgICB0aGlzLmV2ZW50TGlzdGVuZXJzLnB1c2goXHJcbiAgICAgIHRoaXMucmVuZGVyZXIubGlzdGVuKFxyXG4gICAgICAgIFwid2luZG93XCIsXHJcbiAgICAgICAgXCJ0b3VjaHN0YXJ0XCIsXHJcbiAgICAgICAgdGhpcy5fb25Ub3VjaFN0YXJ0LmJpbmQodGhpcylcclxuICAgICAgKSxcclxuICAgICAgdGhpcy5yZW5kZXJlci5saXN0ZW4oXCJ3aW5kb3dcIiwgXCJ0b3VjaG1vdmVcIiwgdGhpcy5fb25Ub3VjaE1vdmUuYmluZCh0aGlzKSksXHJcbiAgICAgIHRoaXMucmVuZGVyZXIubGlzdGVuKFwid2luZG93XCIsIFwidG91Y2hlbmRcIiwgdGhpcy5fb25Ub3VjaEVuZC5iaW5kKHRoaXMpKVxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgX29uVG91Y2hTdGFydChldmVudDogVG91Y2hFdmVudCk6IHZvaWQge1xyXG4gICAgdGhpcy5hY3RpdmVQYXRoID0gdHJ1ZTtcclxuICAgIHRoaXMuY29udGV4dC5iZWdpblBhdGgoKTtcclxuICAgIHRoaXMucHJldmlvdXNQb3NpdGlvbiA9IHRoaXMuZ2V0UG9zaXRpb24oXHJcbiAgICAgIGV2ZW50LnRvdWNoZXNbMF0uY2xpZW50WCxcclxuICAgICAgZXZlbnQudG91Y2hlc1swXS5jbGllbnRZXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfb25Ub3VjaE1vdmUoZXZlbnQ6IFRvdWNoRXZlbnQpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmFjdGl2ZVBhdGgpIHtcclxuICAgICAgdGhpcy5fZHJhd0xpbmUoZXZlbnQudG91Y2hlc1swXSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF9vblRvdWNoRW5kKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuYWN0aXZlUGF0aCkge1xyXG4gICAgICB0aGlzLmNvbnRleHQuY2xvc2VQYXRoKCk7XHJcbiAgICAgIHRoaXMuYWN0aXZlUGF0aCA9IGZhbHNlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLmV2ZW50TGlzdGVuZXJzLmZvckVhY2goKHVubGlzdGVuKSA9PiB1bmxpc3RlbigpKTtcclxuICB9XHJcbn1cclxuIiwiPGRpdiBjbGFzcz1cImNhbnZhcy13cmFwcGVyXCI+XHJcbiAgPGNhbnZhcyBpZD1cImNhbnZhc1wiICNkcmF3aW5nQ2FudmFzPjwvY2FudmFzPlxyXG48L2Rpdj5cclxuPGRpdiBjbGFzcz1cImltYWdlLWJ1dHRvbi13cmFwcGVyXCI+XHJcbiAgPGJ1dHRvblxyXG4gICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAoY2xpY2spPVwic2F2ZSgpXCJcclxuICAgIGNsYXNzPVwiYnV0dG9uIHNhdmVcIlxyXG4gICAgW3N0eWxlLmJhY2tncm91bmQtY29sb3JdPVwic2F2ZUJ1dHRvbkNvbG9yXCJcclxuICA+XHJcbiAgICBTYXZlXHJcbiAgPC9idXR0b24+XHJcbiAgPGJ1dHRvblxyXG4gICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAoY2xpY2spPVwiY2xlYXIoKVwiXHJcbiAgICBjbGFzcz1cImJ1dHRvbiB1bmRvXCJcclxuICAgIFtzdHlsZS5iYWNrZ3JvdW5kLWNvbG9yXT1cInVuZG9CdXR0b25Db2xvclwiXHJcbiAgPlxyXG4gICAgVW5kb1xyXG4gIDwvYnV0dG9uPlxyXG48L2Rpdj5cclxuIl19
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generated bundle index. Do not edit.
|
|
3
|
-
*/
|
|
4
|
-
export * from './public-api';
|
|
5
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWVhc3ktaW1hZ2UtZHJhd2luZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL25neC1lYXN5LWltYWdlLWRyYXdpbmcvc3JjL25neC1lYXN5LWltYWdlLWRyYXdpbmcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLGNBQWMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR2VuZXJhdGVkIGJ1bmRsZSBpbmRleC4gRG8gbm90IGVkaXQuXG4gKi9cblxuZXhwb3J0ICogZnJvbSAnLi9wdWJsaWMtYXBpJztcbiJdfQ==
|
package/esm2022/public-api.mjs
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Public API Surface of ngx-easy-image-drawing
|
|
3
|
-
*/
|
|
4
|
-
export * from "./lib/easy-image-drawing.component";
|
|
5
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL25neC1lYXN5LWltYWdlLWRyYXdpbmcvc3JjL3B1YmxpYy1hcGkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLG9DQUFvQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLypcclxuICogUHVibGljIEFQSSBTdXJmYWNlIG9mIG5neC1lYXN5LWltYWdlLWRyYXdpbmdcclxuICovXHJcblxyXG5leHBvcnQgKiBmcm9tIFwiLi9saWIvZWFzeS1pbWFnZS1kcmF3aW5nLmNvbXBvbmVudFwiO1xyXG4iXX0=
|