ngx-easy-image-drawing 0.0.1
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 +24 -0
- package/esm2022/lib/ngx-easy-image-drawing.component.mjs +114 -0
- package/esm2022/ngx-easy-image-drawing.mjs +5 -0
- package/esm2022/public-api.mjs +5 -0
- package/fesm2022/ngx-easy-image-drawing.mjs +125 -0
- package/fesm2022/ngx-easy-image-drawing.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/ngx-easy-image-drawing.component.d.ts +26 -0
- package/package.json +36 -0
- package/public-api.d.ts +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# NgxEasyImageDrawing
|
|
2
|
+
|
|
3
|
+
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 18.1.0.
|
|
4
|
+
|
|
5
|
+
## Code scaffolding
|
|
6
|
+
|
|
7
|
+
Run `ng generate component component-name --project ngx-easy-image-drawing` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ngx-easy-image-drawing`.
|
|
8
|
+
> Note: Don't forget to add `--project ngx-easy-image-drawing` or else it will be added to the default project in your `angular.json` file.
|
|
9
|
+
|
|
10
|
+
## Build
|
|
11
|
+
|
|
12
|
+
Run `ng build ngx-easy-image-drawing` to build the project. The build artifacts will be stored in the `dist/` directory.
|
|
13
|
+
|
|
14
|
+
## Publishing
|
|
15
|
+
|
|
16
|
+
After building your library with `ng build ngx-easy-image-drawing`, go to the dist folder `cd dist/ngx-easy-image-drawing` and run `npm publish`.
|
|
17
|
+
|
|
18
|
+
## Running unit tests
|
|
19
|
+
|
|
20
|
+
Run `ng test ngx-easy-image-drawing` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
|
21
|
+
|
|
22
|
+
## Further help
|
|
23
|
+
|
|
24
|
+
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { Component, ViewChild, Input, Output, EventEmitter, } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export class NgxEasyImageDrawingComponent {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.width = 500;
|
|
6
|
+
this.height = 500;
|
|
7
|
+
this.lineWidth = 7;
|
|
8
|
+
this.lineColor = '#000000';
|
|
9
|
+
this.src = '';
|
|
10
|
+
this.savedImage = new EventEmitter();
|
|
11
|
+
this.previousPosition = { x: 0, y: 0 };
|
|
12
|
+
this.activePath = false;
|
|
13
|
+
this._mousedown = null;
|
|
14
|
+
this._mousemove = null;
|
|
15
|
+
this._mouseup = null;
|
|
16
|
+
}
|
|
17
|
+
ngAfterViewInit() {
|
|
18
|
+
this.canvas.nativeElement.width = this.width;
|
|
19
|
+
this.canvas.nativeElement.height = this.height;
|
|
20
|
+
this.context = this.canvas.nativeElement.getContext('2d');
|
|
21
|
+
this.context.lineWidth = this.lineWidth;
|
|
22
|
+
this.context.strokeStyle = this.lineColor;
|
|
23
|
+
this.context.lineCap = 'round';
|
|
24
|
+
// set src to image
|
|
25
|
+
const image = new Image();
|
|
26
|
+
image.src = this.src;
|
|
27
|
+
image.onload = () => {
|
|
28
|
+
this.context.drawImage(image, 0, 0, this.width, this.height);
|
|
29
|
+
};
|
|
30
|
+
this._mousedown = window.addEventListener('mousedown', (event) => {
|
|
31
|
+
this.activePath = true;
|
|
32
|
+
this.context.beginPath();
|
|
33
|
+
this.previousPosition = this.getMousePosition(event);
|
|
34
|
+
});
|
|
35
|
+
this._mousemove = window.addEventListener('mousemove', (event) => {
|
|
36
|
+
event.preventDefault();
|
|
37
|
+
if (this.activePath) {
|
|
38
|
+
this._drawLine(event);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
this._mouseup = window.addEventListener('mouseup', () => {
|
|
42
|
+
if (this.activePath) {
|
|
43
|
+
this.context.closePath();
|
|
44
|
+
this.activePath = false;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
save() {
|
|
49
|
+
const dataUrl = this.canvas.nativeElement.toDataURL('image/png');
|
|
50
|
+
const blob = this._dataURItoBlob(dataUrl);
|
|
51
|
+
this.savedImage.next(new File([blob], 'image.png'));
|
|
52
|
+
}
|
|
53
|
+
clear() {
|
|
54
|
+
this.context.clearRect(0, 0, this.width, this.height);
|
|
55
|
+
const image = new Image();
|
|
56
|
+
image.src = this.src;
|
|
57
|
+
image.onload = () => {
|
|
58
|
+
this.context.drawImage(image, 0, 0, this.width, this.height);
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
_dataURItoBlob(dataUrl) {
|
|
62
|
+
const byteString = atob(dataUrl.split(',')[1]);
|
|
63
|
+
const mimeString = dataUrl.split(',')[0].split(':')[1].split(';')[0];
|
|
64
|
+
const ab = new ArrayBuffer(byteString.length);
|
|
65
|
+
const dw = new DataView(ab);
|
|
66
|
+
for (let i = 0; i < byteString.length; i++) {
|
|
67
|
+
dw.setUint8(i, byteString.charCodeAt(i));
|
|
68
|
+
}
|
|
69
|
+
return new Blob([ab], { type: mimeString });
|
|
70
|
+
}
|
|
71
|
+
_drawLine(event) {
|
|
72
|
+
const currentPosition = this.getMousePosition(event);
|
|
73
|
+
this.context.moveTo(this.previousPosition.x, this.previousPosition.y);
|
|
74
|
+
this.context.lineTo(currentPosition.x, currentPosition.y);
|
|
75
|
+
this.previousPosition = currentPosition;
|
|
76
|
+
this.context.stroke();
|
|
77
|
+
}
|
|
78
|
+
getMousePosition(event) {
|
|
79
|
+
const rect = this.canvas.nativeElement.getBoundingClientRect();
|
|
80
|
+
const scaleX = this.canvas.nativeElement.width / rect.width;
|
|
81
|
+
const scaleY = this.canvas.nativeElement.height / rect.height;
|
|
82
|
+
return {
|
|
83
|
+
x: (event.clientX - rect.left) * scaleX,
|
|
84
|
+
y: (event.clientY - rect.top) * scaleY,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
ngOnDestroy() {
|
|
88
|
+
window.removeEventListener('mousedown', this._mousedown);
|
|
89
|
+
window.removeEventListener('mousemove', this._mousemove);
|
|
90
|
+
window.removeEventListener('mouseup', this._mouseup);
|
|
91
|
+
}
|
|
92
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: NgxEasyImageDrawingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
93
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.1.3", type: NgxEasyImageDrawingComponent, isStandalone: true, selector: "lib-ngx-easy-image-drawing", inputs: { width: "width", height: "height", lineWidth: "lineWidth", lineColor: "lineColor", src: "src" }, outputs: { savedImage: "savedImage" }, viewQueries: [{ propertyName: "canvas", first: true, predicate: ["drawingCanvas"], descendants: true }], ngImport: i0, template: ` <p>ngx-easy-image-drawing works!</p> `, isInline: true, styles: [""] }); }
|
|
94
|
+
}
|
|
95
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: NgxEasyImageDrawingComponent, decorators: [{
|
|
96
|
+
type: Component,
|
|
97
|
+
args: [{ selector: 'lib-ngx-easy-image-drawing', standalone: true, imports: [], template: ` <p>ngx-easy-image-drawing works!</p> ` }]
|
|
98
|
+
}], propDecorators: { width: [{
|
|
99
|
+
type: Input
|
|
100
|
+
}], height: [{
|
|
101
|
+
type: Input
|
|
102
|
+
}], lineWidth: [{
|
|
103
|
+
type: Input
|
|
104
|
+
}], lineColor: [{
|
|
105
|
+
type: Input
|
|
106
|
+
}], src: [{
|
|
107
|
+
type: Input
|
|
108
|
+
}], savedImage: [{
|
|
109
|
+
type: Output
|
|
110
|
+
}], canvas: [{
|
|
111
|
+
type: ViewChild,
|
|
112
|
+
args: ['drawingCanvas']
|
|
113
|
+
}] } });
|
|
114
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWVhc3ktaW1hZ2UtZHJhd2luZy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZWFzeS1pbWFnZS1kcmF3aW5nL3NyYy9saWIvbmd4LWVhc3ktaW1hZ2UtZHJhd2luZy5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCxTQUFTLEVBR1QsS0FBSyxFQUNMLE1BQU0sRUFDTixZQUFZLEdBRWIsTUFBTSxlQUFlLENBQUM7O0FBU3ZCLE1BQU0sT0FBTyw0QkFBNEI7SUFQekM7UUFRVyxVQUFLLEdBQVcsR0FBRyxDQUFDO1FBQ3BCLFdBQU0sR0FBVyxHQUFHLENBQUM7UUFDckIsY0FBUyxHQUFHLENBQUMsQ0FBQztRQUNkLGNBQVMsR0FBRyxTQUFTLENBQUM7UUFDdEIsUUFBRyxHQUFHLEVBQUUsQ0FBQztRQUNSLGVBQVUsR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO1FBTXhDLHFCQUFnQixHQUE2QixFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO1FBQzVELGVBQVUsR0FBRyxLQUFLLENBQUM7UUFFbkIsZUFBVSxHQUFRLElBQUksQ0FBQztRQUN2QixlQUFVLEdBQVEsSUFBSSxDQUFDO1FBQ3ZCLGFBQVEsR0FBUSxJQUFJLENBQUM7S0EyRjlCO0lBekZDLGVBQWU7UUFDYixJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQztRQUM3QyxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUUvQyxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUUsQ0FBQztRQUMzRCxJQUFJLENBQUMsT0FBTyxDQUFD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LCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIENvbXBvbmVudCxcclxuICBWaWV3Q2hpbGQsXHJcbiAgRWxlbWVudFJlZixcclxuICBBZnRlclZpZXdJbml0LFxyXG4gIElucHV0LFxyXG4gIE91dHB1dCxcclxuICBFdmVudEVtaXR0ZXIsXHJcbiAgT25EZXN0cm95LFxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdsaWItbmd4LWVhc3ktaW1hZ2UtZHJhd2luZycsXHJcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcclxuICBpbXBvcnRzOiBbXSxcclxuICB0ZW1wbGF0ZTogYCA8cD5uZ3gtZWFzeS1pbWFnZS1kcmF3aW5nIHdvcmtzITwvcD4gYCxcclxuICBzdHlsZXM6IGBgLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgTmd4RWFzeUltYWdlRHJhd2luZ0NvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XHJcbiAgQElucHV0KCkgd2lkdGg6IG51bWJlciA9IDUwMDtcclxuICBASW5wdXQoKSBoZWlnaHQ6IG51bWJlciA9IDUwMDtcclxuICBASW5wdXQoKSBsaW5lV2lkdGggPSA3O1xyXG4gIEBJbnB1dCgpIGxpbmVDb2xvciA9ICcjMDAwMDAwJztcclxuICBASW5wdXQoKSBzcmMgPSAnJztcclxuICBAT3V0cHV0KCkgc2F2ZWRJbWFnZSA9IG5ldyBFdmVudEVtaXR0ZXI8RmlsZT4oKTtcclxuXHJcbiAgLy8gaXRzIGltcG9ydGFudCBteUNhbnZhcyBtYXRjaGVzIHRoZSB2YXJpYWJsZSBuYW1lIGluIHRoZSB0ZW1wbGF0ZVxyXG4gIEBWaWV3Q2hpbGQoJ2RyYXdpbmdDYW52YXMnKSBjYW52YXMhOiBFbGVtZW50UmVmPEhUTUxDYW52YXNFbGVtZW50PjtcclxuXHJcbiAgY29udGV4dCE6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDtcclxuICBwcml2YXRlIHByZXZpb3VzUG9zaXRpb246IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSA9IHsgeDogMCwgeTogMCB9O1xyXG4gIHByaXZhdGUgYWN0aXZlUGF0aCA9IGZhbHNlO1xyXG5cclxuICBwcml2YXRlIF9tb3VzZWRvd246IGFueSA9IG51bGw7XHJcbiAgcHJpdmF0ZSBfbW91c2Vtb3ZlOiBhbnkgPSBudWxsO1xyXG4gIHByaXZhdGUgX21vdXNldXA6IGFueSA9IG51bGw7XHJcblxyXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcclxuICAgIHRoaXMuY2FudmFzLm5hdGl2ZUVsZW1lbnQud2lkdGggPSB0aGlzLndpZHRoO1xyXG4gICAgdGhpcy5jYW52YXMubmF0aXZlRWxlbWVudC5oZWlnaHQgPSB0aGlzLmhlaWdodDtcclxuXHJcbiAgICB0aGlzLmNvbnRleHQgPSB0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50LmdldENvbnRleHQoJzJkJykhO1xyXG4gICAgdGhpcy5jb250ZXh0LmxpbmVXaWR0aCA9IHRoaXMubGluZVdpZHRoO1xyXG4gICAgdGhpcy5jb250ZXh0LnN0cm9rZVN0eWxlID0gdGhpcy5saW5lQ29sb3I7XHJcbiAgICB0aGlzLmNvbnRleHQubGluZUNhcCA9ICdyb3VuZCc7XHJcblxyXG4gICAgLy8gc2V0IHNyYyB0byBpbWFnZVxyXG4gICAgY29uc3QgaW1hZ2UgPSBuZXcgSW1hZ2UoKTtcclxuICAgIGltYWdlLnNyYyA9IHRoaXMuc3JjO1xyXG4gICAgaW1hZ2Uub25sb2FkID0gKCkgPT4ge1xyXG4gICAgICB0aGlzLmNvbnRleHQuZHJhd0ltYWdlKGltYWdlLCAwLCAwLCB0aGlzLndpZHRoLCB0aGlzLmhlaWdodCk7XHJcbiAgICB9O1xyXG5cclxuICAgIHRoaXMuX21vdXNlZG93biA9IHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFxyXG4gICAgICAnbW91c2Vkb3duJyxcclxuICAgICAgKGV2ZW50OiBNb3VzZUV2ZW50KSA9PiB7XHJcbiAgICAgICAgdGhpcy5hY3RpdmVQYXRoID0gdHJ1ZTtcclxuICAgICAgICB0aGlzLmNvbnRleHQuYmVnaW5QYXRoKCk7XHJcbiAgICAgICAgdGhpcy5wcmV2aW91c1Bvc2l0aW9uID0gdGhpcy5nZXRNb3VzZVBvc2l0aW9uKGV2ZW50KTtcclxuICAgICAgfVxyXG4gICAgKTtcclxuXHJcbiAgICB0aGlzLl9tb3VzZW1vdmUgPSB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgKGV2ZW50KSA9PiB7XHJcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgIGlmICh0aGlzLmFjdGl2ZVBhdGgpIHtcclxuICAgICAgICB0aGlzLl9kcmF3TGluZShldmVudCk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIHRoaXMuX21vdXNldXAgPSB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsICgpID0+IHtcclxuICAgICAgaWYgKHRoaXMuYWN0aXZlUGF0aCkge1xyXG4gICAgICAgIHRoaXMuY29udGV4dC5jbG9zZVBhdGgoKTtcclxuICAgICAgICB0aGlzLmFjdGl2ZVBhdGggPSBmYWxzZTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgc2F2ZSgpOiB2b2lkIHtcclxuICAgIGNvbnN0IGRhdGFVcmwgPSB0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50LnRvRGF0YVVSTCgnaW1hZ2UvcG5nJyk7XHJcbiAgICBjb25zdCBibG9iID0gdGhpcy5fZGF0YVVSSXRvQmxvYihkYXRhVXJsKTtcclxuICAgIHRoaXMuc2F2ZWRJbWFnZS5uZXh0KG5ldyBGaWxlKFtibG9iXSwgJ2ltYWdlLnBuZycpKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBjbGVhcigpOiB2b2lkIHtcclxuICAgIHRoaXMuY29udGV4dC5jbGVhclJlY3QoMCwgMCwgdGhpcy53aWR0aCwgdGhpcy5oZWlnaHQpO1xyXG4gICAgY29uc3QgaW1hZ2UgPSBuZXcgSW1hZ2UoKTtcclxuICAgIGltYWdlLnNyYyA9IHRoaXMuc3JjO1xyXG4gICAgaW1hZ2Uub25sb2FkID0gKCkgPT4ge1xyXG4gICAgICB0aGlzLmNvbnRleHQuZHJhd0ltYWdlKGltYWdlLCAwLCAwLCB0aGlzLndpZHRoLCB0aGlzLmhlaWdodCk7XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfZGF0YVVSSXRvQmxvYihkYXRhVXJsOiBzdHJpbmcpIHtcclxuICAgIGNvbnN0IGJ5dGVTdHJpbmcgPSBhdG9iKGRhdGFVcmwuc3BsaXQoJywnKVsxXSk7XHJcbiAgICBjb25zdCBtaW1lU3RyaW5nID0gZGF0YVVybC5zcGxpdCgnLCcpWzBdLnNwbGl0KCc6JylbMV0uc3BsaXQoJzsnKVswXTtcclxuICAgIGNvbnN0IGFiID0gbmV3IEFycmF5QnVmZmVyKGJ5dGVTdHJpbmcubGVuZ3RoKTtcclxuICAgIGNvbnN0IGR3ID0gbmV3IERhdGFWaWV3KGFiKTtcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYnl0ZVN0cmluZy5sZW5ndGg7IGkrKykge1xyXG4gICAgICBkdy5zZXRVaW50OChpLCBieXRlU3RyaW5nLmNoYXJDb2RlQXQoaSkpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG5ldyBCbG9iKFthYl0sIHsgdHlwZTogbWltZVN0cmluZyB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgX2RyYXdMaW5lKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XHJcbiAgICBjb25zdCBjdXJyZW50UG9zaXRpb24gPSB0aGlzLmdldE1vdXNlUG9zaXRpb24oZXZlbnQpO1xyXG4gICAgdGhpcy5jb250ZXh0Lm1vdmVUbyh0aGlzLnByZXZpb3VzUG9zaXRpb24ueCwgdGhpcy5wcmV2aW91c1Bvc2l0aW9uLnkpO1xyXG4gICAgdGhpcy5jb250ZXh0LmxpbmVUbyhjdXJyZW50UG9zaXRpb24ueCwgY3VycmVudFBvc2l0aW9uLnkpO1xyXG4gICAgdGhpcy5wcmV2aW91c1Bvc2l0aW9uID0gY3VycmVudFBvc2l0aW9uO1xyXG4gICAgdGhpcy5jb250ZXh0LnN0cm9rZSgpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBnZXRNb3VzZVBvc2l0aW9uKGV2ZW50OiBNb3VzZUV2ZW50KTogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9IHtcclxuICAgIGNvbnN0IHJlY3QgPSB0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xyXG4gICAgY29uc3Qgc2NhbGVYID0gdGhpcy5jYW52YXMubmF0aXZlRWxlbWVudC53aWR0aCAvIHJlY3Qud2lkdGg7XHJcbiAgICBjb25zdCBzY2FsZVkgPSB0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50LmhlaWdodCAvIHJlY3QuaGVpZ2h0O1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgeDogKGV2ZW50LmNsaWVudFggLSByZWN0LmxlZnQpICogc2NhbGVYLFxyXG4gICAgICB5OiAoZXZlbnQuY2xpZW50WSAtIHJlY3QudG9wKSAqIHNjYWxlWSxcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB0aGlzLl9tb3VzZWRvd24pO1xyXG4gICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX21vdXNlbW92ZSk7XHJcbiAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMuX21vdXNldXApO1xyXG4gIH1cclxufVxyXG4iXX0=
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generated bundle index. Do not edit.
|
|
3
|
+
*/
|
|
4
|
+
export * from './public-api';
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWVhc3ktaW1hZ2UtZHJhd2luZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL25neC1lYXN5LWltYWdlLWRyYXdpbmcvc3JjL25neC1lYXN5LWltYWdlLWRyYXdpbmcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLGNBQWMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR2VuZXJhdGVkIGJ1bmRsZSBpbmRleC4gRG8gbm90IGVkaXQuXG4gKi9cblxuZXhwb3J0ICogZnJvbSAnLi9wdWJsaWMtYXBpJztcbiJdfQ==
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Public API Surface of ngx-easy-image-drawing
|
|
3
|
+
*/
|
|
4
|
+
export * from './lib/ngx-easy-image-drawing.component';
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL25neC1lYXN5LWltYWdlLWRyYXdpbmcvc3JjL3B1YmxpYy1hcGkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLHdDQUF3QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLypcclxuICogUHVibGljIEFQSSBTdXJmYWNlIG9mIG5neC1lYXN5LWltYWdlLWRyYXdpbmdcclxuICovXHJcblxyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9uZ3gtZWFzeS1pbWFnZS1kcmF3aW5nLmNvbXBvbmVudCc7XHJcbiJdfQ==
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { EventEmitter, Component, Input, Output, ViewChild } from '@angular/core';
|
|
3
|
+
|
|
4
|
+
class NgxEasyImageDrawingComponent {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.width = 500;
|
|
7
|
+
this.height = 500;
|
|
8
|
+
this.lineWidth = 7;
|
|
9
|
+
this.lineColor = '#000000';
|
|
10
|
+
this.src = '';
|
|
11
|
+
this.savedImage = new EventEmitter();
|
|
12
|
+
this.previousPosition = { x: 0, y: 0 };
|
|
13
|
+
this.activePath = false;
|
|
14
|
+
this._mousedown = null;
|
|
15
|
+
this._mousemove = null;
|
|
16
|
+
this._mouseup = null;
|
|
17
|
+
}
|
|
18
|
+
ngAfterViewInit() {
|
|
19
|
+
this.canvas.nativeElement.width = this.width;
|
|
20
|
+
this.canvas.nativeElement.height = this.height;
|
|
21
|
+
this.context = this.canvas.nativeElement.getContext('2d');
|
|
22
|
+
this.context.lineWidth = this.lineWidth;
|
|
23
|
+
this.context.strokeStyle = this.lineColor;
|
|
24
|
+
this.context.lineCap = 'round';
|
|
25
|
+
// set src to image
|
|
26
|
+
const image = new Image();
|
|
27
|
+
image.src = this.src;
|
|
28
|
+
image.onload = () => {
|
|
29
|
+
this.context.drawImage(image, 0, 0, this.width, this.height);
|
|
30
|
+
};
|
|
31
|
+
this._mousedown = window.addEventListener('mousedown', (event) => {
|
|
32
|
+
this.activePath = true;
|
|
33
|
+
this.context.beginPath();
|
|
34
|
+
this.previousPosition = this.getMousePosition(event);
|
|
35
|
+
});
|
|
36
|
+
this._mousemove = window.addEventListener('mousemove', (event) => {
|
|
37
|
+
event.preventDefault();
|
|
38
|
+
if (this.activePath) {
|
|
39
|
+
this._drawLine(event);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
this._mouseup = window.addEventListener('mouseup', () => {
|
|
43
|
+
if (this.activePath) {
|
|
44
|
+
this.context.closePath();
|
|
45
|
+
this.activePath = false;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
save() {
|
|
50
|
+
const dataUrl = this.canvas.nativeElement.toDataURL('image/png');
|
|
51
|
+
const blob = this._dataURItoBlob(dataUrl);
|
|
52
|
+
this.savedImage.next(new File([blob], 'image.png'));
|
|
53
|
+
}
|
|
54
|
+
clear() {
|
|
55
|
+
this.context.clearRect(0, 0, this.width, this.height);
|
|
56
|
+
const image = new Image();
|
|
57
|
+
image.src = this.src;
|
|
58
|
+
image.onload = () => {
|
|
59
|
+
this.context.drawImage(image, 0, 0, this.width, this.height);
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
_dataURItoBlob(dataUrl) {
|
|
63
|
+
const byteString = atob(dataUrl.split(',')[1]);
|
|
64
|
+
const mimeString = dataUrl.split(',')[0].split(':')[1].split(';')[0];
|
|
65
|
+
const ab = new ArrayBuffer(byteString.length);
|
|
66
|
+
const dw = new DataView(ab);
|
|
67
|
+
for (let i = 0; i < byteString.length; i++) {
|
|
68
|
+
dw.setUint8(i, byteString.charCodeAt(i));
|
|
69
|
+
}
|
|
70
|
+
return new Blob([ab], { type: mimeString });
|
|
71
|
+
}
|
|
72
|
+
_drawLine(event) {
|
|
73
|
+
const currentPosition = this.getMousePosition(event);
|
|
74
|
+
this.context.moveTo(this.previousPosition.x, this.previousPosition.y);
|
|
75
|
+
this.context.lineTo(currentPosition.x, currentPosition.y);
|
|
76
|
+
this.previousPosition = currentPosition;
|
|
77
|
+
this.context.stroke();
|
|
78
|
+
}
|
|
79
|
+
getMousePosition(event) {
|
|
80
|
+
const rect = this.canvas.nativeElement.getBoundingClientRect();
|
|
81
|
+
const scaleX = this.canvas.nativeElement.width / rect.width;
|
|
82
|
+
const scaleY = this.canvas.nativeElement.height / rect.height;
|
|
83
|
+
return {
|
|
84
|
+
x: (event.clientX - rect.left) * scaleX,
|
|
85
|
+
y: (event.clientY - rect.top) * scaleY,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
ngOnDestroy() {
|
|
89
|
+
window.removeEventListener('mousedown', this._mousedown);
|
|
90
|
+
window.removeEventListener('mousemove', this._mousemove);
|
|
91
|
+
window.removeEventListener('mouseup', this._mouseup);
|
|
92
|
+
}
|
|
93
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: NgxEasyImageDrawingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
94
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.1.3", type: NgxEasyImageDrawingComponent, isStandalone: true, selector: "lib-ngx-easy-image-drawing", inputs: { width: "width", height: "height", lineWidth: "lineWidth", lineColor: "lineColor", src: "src" }, outputs: { savedImage: "savedImage" }, viewQueries: [{ propertyName: "canvas", first: true, predicate: ["drawingCanvas"], descendants: true }], ngImport: i0, template: ` <p>ngx-easy-image-drawing works!</p> `, isInline: true, styles: [""] }); }
|
|
95
|
+
}
|
|
96
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: NgxEasyImageDrawingComponent, decorators: [{
|
|
97
|
+
type: Component,
|
|
98
|
+
args: [{ selector: 'lib-ngx-easy-image-drawing', standalone: true, imports: [], template: ` <p>ngx-easy-image-drawing works!</p> ` }]
|
|
99
|
+
}], propDecorators: { width: [{
|
|
100
|
+
type: Input
|
|
101
|
+
}], height: [{
|
|
102
|
+
type: Input
|
|
103
|
+
}], lineWidth: [{
|
|
104
|
+
type: Input
|
|
105
|
+
}], lineColor: [{
|
|
106
|
+
type: Input
|
|
107
|
+
}], src: [{
|
|
108
|
+
type: Input
|
|
109
|
+
}], savedImage: [{
|
|
110
|
+
type: Output
|
|
111
|
+
}], canvas: [{
|
|
112
|
+
type: ViewChild,
|
|
113
|
+
args: ['drawingCanvas']
|
|
114
|
+
}] } });
|
|
115
|
+
|
|
116
|
+
/*
|
|
117
|
+
* Public API Surface of ngx-easy-image-drawing
|
|
118
|
+
*/
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Generated bundle index. Do not edit.
|
|
122
|
+
*/
|
|
123
|
+
|
|
124
|
+
export { NgxEasyImageDrawingComponent };
|
|
125
|
+
//# sourceMappingURL=ngx-easy-image-drawing.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngx-easy-image-drawing.mjs","sources":["../../../projects/ngx-easy-image-drawing/src/lib/ngx-easy-image-drawing.component.ts","../../../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} from '@angular/core';\r\n\r\n@Component({\r\n selector: 'lib-ngx-easy-image-drawing',\r\n standalone: true,\r\n imports: [],\r\n template: ` <p>ngx-easy-image-drawing works!</p> `,\r\n styles: ``,\r\n})\r\nexport class NgxEasyImageDrawingComponent implements AfterViewInit, OnDestroy {\r\n @Input() width: number = 500;\r\n @Input() height: number = 500;\r\n @Input() lineWidth = 7;\r\n @Input() lineColor = '#000000';\r\n @Input() src = '';\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\r\n private _mousedown: any = null;\r\n private _mousemove: any = null;\r\n private _mouseup: any = null;\r\n\r\n ngAfterViewInit(): void {\r\n this.canvas.nativeElement.width = this.width;\r\n this.canvas.nativeElement.height = this.height;\r\n\r\n this.context = this.canvas.nativeElement.getContext('2d')!;\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 this._mousedown = window.addEventListener(\r\n 'mousedown',\r\n (event: MouseEvent) => {\r\n this.activePath = true;\r\n this.context.beginPath();\r\n this.previousPosition = this.getMousePosition(event);\r\n }\r\n );\r\n\r\n this._mousemove = window.addEventListener('mousemove', (event) => {\r\n event.preventDefault();\r\n if (this.activePath) {\r\n this._drawLine(event);\r\n }\r\n });\r\n\r\n this._mouseup = window.addEventListener('mouseup', () => {\r\n if (this.activePath) {\r\n this.context.closePath();\r\n this.activePath = false;\r\n }\r\n });\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): void {\r\n const currentPosition = this.getMousePosition(event);\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 getMousePosition(event: MouseEvent): { 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: (event.clientX - rect.left) * scaleX,\r\n y: (event.clientY - rect.top) * scaleY,\r\n };\r\n }\r\n\r\n ngOnDestroy(): void {\r\n window.removeEventListener('mousedown', this._mousedown);\r\n window.removeEventListener('mousemove', this._mousemove);\r\n window.removeEventListener('mouseup', this._mouseup);\r\n }\r\n}\r\n","/*\r\n * Public API Surface of ngx-easy-image-drawing\r\n */\r\n\r\nexport * from './lib/ngx-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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"}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ElementRef, AfterViewInit, EventEmitter, OnDestroy } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export declare class NgxEasyImageDrawingComponent implements AfterViewInit, OnDestroy {
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
lineWidth: number;
|
|
7
|
+
lineColor: string;
|
|
8
|
+
src: string;
|
|
9
|
+
savedImage: EventEmitter<File>;
|
|
10
|
+
canvas: ElementRef<HTMLCanvasElement>;
|
|
11
|
+
context: CanvasRenderingContext2D;
|
|
12
|
+
private previousPosition;
|
|
13
|
+
private activePath;
|
|
14
|
+
private _mousedown;
|
|
15
|
+
private _mousemove;
|
|
16
|
+
private _mouseup;
|
|
17
|
+
ngAfterViewInit(): void;
|
|
18
|
+
save(): void;
|
|
19
|
+
clear(): void;
|
|
20
|
+
private _dataURItoBlob;
|
|
21
|
+
private _drawLine;
|
|
22
|
+
private getMousePosition;
|
|
23
|
+
ngOnDestroy(): void;
|
|
24
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<NgxEasyImageDrawingComponent, never>;
|
|
25
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<NgxEasyImageDrawingComponent, "lib-ngx-easy-image-drawing", never, { "width": { "alias": "width"; "required": false; }; "height": { "alias": "height"; "required": false; }; "lineWidth": { "alias": "lineWidth"; "required": false; }; "lineColor": { "alias": "lineColor"; "required": false; }; "src": { "alias": "src"; "required": false; }; }, { "savedImage": "savedImage"; }, never, never, true, never>;
|
|
26
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ngx-easy-image-drawing",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"peerDependencies": {
|
|
5
|
+
"@angular/common": "^18.1.0",
|
|
6
|
+
"@angular/core": "^18.1.0"
|
|
7
|
+
},
|
|
8
|
+
"description": "Angular library for easy image drawing on canvas",
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"tslib": "^2.3.0"
|
|
11
|
+
},
|
|
12
|
+
"sideEffects": false,
|
|
13
|
+
"module": "fesm2022/ngx-easy-image-drawing.mjs",
|
|
14
|
+
"typings": "index.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
"./package.json": {
|
|
17
|
+
"default": "./package.json"
|
|
18
|
+
},
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./index.d.ts",
|
|
21
|
+
"esm2022": "./esm2022/ngx-easy-image-drawing.mjs",
|
|
22
|
+
"esm": "./esm2022/ngx-easy-image-drawing.mjs",
|
|
23
|
+
"default": "./fesm2022/ngx-easy-image-drawing.mjs"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"git repository": "",
|
|
27
|
+
"keywords": [
|
|
28
|
+
"image",
|
|
29
|
+
"drawing",
|
|
30
|
+
"canvas",
|
|
31
|
+
"angular",
|
|
32
|
+
"ngx"
|
|
33
|
+
],
|
|
34
|
+
"author": "Alex Voronin <alex.varonin@gmail.com>",
|
|
35
|
+
"license": "ISC"
|
|
36
|
+
}
|
package/public-api.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lib/ngx-easy-image-drawing.component';
|