UNPKG

ngx-image-drawing-sixteen

Version:

![Screenshot](https://github.com/lea-so123/GitHub/main/my-workspace/projects/ngx-image-drawing-zone/.github/screenshot.jpg)

1,012 lines 52.7 kB
import * as i1 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { EventEmitter, Component, Input, Output, NgModule } from '@angular/core';
import { fabric } from 'fabric-ext';
import { Observable, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { MatIconModule } from '@angular/material/icon';

const I18nFr = {
    saveBtn: 'Enregistrer',
    cancelBtn: 'Annuler',
    loadImage: 'Charger une image depuis votre PC',
    loadImageUrl: 'Charger une image depuis une URL',
    loading: 'Chargement',
    loadError: 'Erreur de chargement %@',
    removeImage: 'Supprimer l\'image',
    sizes: {
        small: 'Petit',
        medium: 'Moyen',
        large: 'Gros'
    },
    undo: 'Annuler',
    redo: 'Répter',
    clear: 'Effacer',
    colors: {
        black: 'Noir',
        white: 'Blanc',
        yellow: 'Jaune',
        red: 'Rouge',
        green: 'Vert',
        blue: 'Blue',
        purple: 'Violet'
    },
    tools: {
        brush: 'Pinceau'
    }
};
const I18nEn = {
    saveBtn: 'Save',
    cancelBtn: 'Cancel',
    loadImage: 'Load image',
    loadImageUrl: 'Load image from URL',
    loading: 'Loading',
    loadError: 'Error loading %@',
    removeImage: 'Remove image',
    sizes: {
        small: 'Small',
        medium: 'Medium',
        large: 'Large'
    },
    resize: "Resize",
    undo: 'Undo',
    redo: 'Redo',
    clear: 'Clear',
    crop: 'Crop',
    mask: "Mask",
    colors: {
        black: 'Black',
        white: 'White',
        yellow: 'Yellow',
        red: 'Red',
        green: 'Green',
        blue: 'Blue',
        purple: 'Purple',
    },
    tools: {
        brush: 'Brush'
    }
};
const I18nHe = {
    saveBtn: 'שמירה',
    cancelBtn: 'ביטול',
    loadImage: 'טוען תמונה',
    loadImageUrl: 'טוען תמונה מנתיב',
    loading: 'בטעינה',
    loadError: 'שגיאה בטעינה',
    removeImage: 'הסרת תמונה',
    sizes: {
        small: 'קטן',
        medium: 'בינוני',
        large: 'גדול'
    },
    resize: "שנה גודל",
    undo: 'ביטול',
    redo: 'שחזור',
    clear: 'ניקןי',
    crop: 'חיתוך תמונה',
    mask: 'ריבוע בחירה',
    colors: {
        black: 'שחור',
        white: 'לבן',
        yellow: 'צהוב',
        red: 'אדום',
        green: 'ירוק',
        blue: 'כחול',
        purple: 'סגול',
    },
    tools: {
        brush: 'מברשת'
    }
};
const i18nLanguages = {
    fr: I18nFr,
    en: I18nEn,
    he: I18nHe
};

class ImageDrawingComponent {
    constructor(zone) {
        this.zone = zone;
        this.saveBtnClass = "button btn-primary";
        this.cancelBtnClass = "button btn-light";
        this.forceSizeCanvas = true;
        this.forceSizeExport = false;
        this.enableRemoveImage = false;
        this.enableLoadAnotherImage = false;
        this.enableTooltip = true;
        this.showCancelButton = true;
        this.locale = 'en';
        /* @deprecated Use i18n.saveBtn */
        this.saveBtnText = 'Save';
        /* @deprecated Use i18n.cancelBtn */
        this.cancelBtnText = 'Cancel';
        /* @deprecated Use i18n.loading */
        this.loadingText = 'Loading…';
        /* @deprecated Use i18n.loadError */
        this.errorText = 'Error loading %@';
        this.outputMimeType = 'image/jpeg';
        this.outputQuality = 0.8;
        this.borderCss = 'none';
        this.drawingSizes = {
            small: 5,
            medium: 10,
            large: 25,
        };
        this.colors = {
            black: '#000',
            white: '#fff',
            yellow: '#ffeb3b',
            red: '#f44336',
            blue: '#2196f3',
            green: '#4caf50',
            purple: '#7a08af',
        };
        this.save = new EventEmitter();
        this.cancel = new EventEmitter();
        this.currentTool = '';
        this.currentSize = 'medium';
        this.currentColor = 'black';
        this.i18n = I18nEn;
        this.canUndo = false;
        this.canRedo = false;
        this.isLoading = false;
        this.hasError = false;
        this.errorMessage = '';
        this.stack = [];
        this.stackUndo = [];
        this.stackUndoLocation = [];
        this.colorsName = [];
        this.drawingSizesName = [];
        this.isCrop = false;
        this.pos = [0, 0];
        this.mousex = 0;
        this.mousey = 0;
        this.disabled = true;
        this.lastSelectedPicture = null;
        this.isInsertingCropRectangle = false;
        this.done = false;
    }
    ngOnInit() {
        this.colorsName = Object.keys(this.colors);
        this.drawingSizesName = Object.keys(this.drawingSizes);
        this.initClipPath();
        this.canvas = new fabric.Canvas('canvas', {
            hoverCursor: 'pointer',
            selection: true,
            preserveObjectStacking: true,
            //clipPath:clipPath
            //isDrawingMode: true,
        });
        this.canvas.backgroundColor = 'white';
        if (this.src) {
            this.importPhotoFromSrc(this.src);
            this.r = document.getElementById('canvas').getBoundingClientRect();
            this.pos[0] = this.r.left;
            this.pos[1] = this.r.top;
        }
        else {
            if (!this.width || !this.height) {
                throw new Error('No width or hight given !');
            }
            this.canvas.setWidth(this.width);
            this.canvas.setHeight(this.height);
        }
        //this.canvas.on('')
        this.canvas.on('path:created', () => {
            this.stack = [];
            this.setUndoRedo();
        });
        this.canvas.on('object:added', (e) => {
            // this.target = null;
            // this.mask = null;
            // this.canvas.forEachObject((obj)=> {
            //   //alert(obj.get('id'));
            //   var id = obj.get('id');
            //   if (id === 'target') {
            //     this.target = obj;
            //      this.canvas.setActiveObject(obj);
            //  }
            //   if (id === 'mask') {
            //     //alert(done);
            //     //alert('mask');
            //     this.mask = obj;
            //   }
            // });
        });
        this.canvas.on('object:modified', (e) => {
            const newWidth = e.target.width * e.target.scaleX;
            const newHeight = e.target.height * e.target.scaleY;
            e.target.set({ opacity: 1 });
            debugger;
            //var newWidth = (Math.round(e.target.width/ canvasGrid)) * canvasGrid;
            //var newHeight = (Math.round(e.target.height / canvasGrid)) * canvasGrid;
            if (e.target.width !== newWidth) {
                //e.target.set({ width: newWidth, height: newHeight, scaleX: 1, scaleY: 1, });
            }
            this.imageUsed.scaleToWidth(e.target.width * e.target.scaleX);
            this.imageUsed.scaleToHeight(e.target.height * e.target.scaleY);
            this.canvas.setWidth(e.target.width * e.target.scaleX);
            this.canvas.setHeight(e.target.height * e.target.scaleY);
            e.target.setCoords();
            this.canvas.renderAll();
            const imageStr = this.canvas.toDataURL({
                format: 'jpeg'
            });
            this.canvas.remove(this.imageUsed);
            this.canvas.getObjects().forEach(e => e.opacity = 0);
            this.selectTool('');
            //this.canvas.getObjects()[0].opacity=1
            this.importPhotoFromSrc(imageStr, false, true);
            //this.setUndoRedo()
        });
        this.canvas.on('mouse:down', (o) => {
            if (this.isInsertingCropRectangle == true) {
                console.log('mouse down done = ' + this.done);
                if (this.done) {
                    this.canvas.renderAll();
                    return;
                }
                this.isDown = true;
                var pointer = this.canvas.getPointer(o.e);
                this.origX = pointer.x;
                this.origY = pointer.y;
                this.crop_rect = new fabric.Rect({
                    left: this.origX,
                    top: this.origY,
                    width: pointer.x - this.origX,
                    height: pointer.y - this.origY,
                    opacity: .3,
                    transparentCorners: false,
                    selectable: true,
                    //id: 'mask'
                });
                this.mask = this.crop_rect;
                this.canvas.add(this.crop_rect);
                this.setUndoRedo();
                this.canvas.renderAll();
            }
            else {
            }
        });
        this.canvas.on('mouse:move', (o) => {
            if (this.isInsertingCropRectangle == true) {
                console.log('mouse move done = ' + this.done);
                if (this.done) {
                    this.canvas.renderAll();
                    return;
                }
                if (!this.isDown)
                    return;
                var pointer = this.canvas.getPointer(o.e);
                if (this.origX > pointer.x) {
                    this.crop_rect.set({
                        left: Math.abs(pointer.x)
                    });
                }
                if (this.origY > pointer.y) {
                    this.crop_rect.set({
                        top: Math.abs(pointer.y)
                    });
                }
                this.crop_rect.set({
                    width: Math.abs(this.origX - pointer.x)
                });
                this.crop_rect.set({
                    height: Math.abs(this.origY - pointer.y)
                });
                this.crop_rect.setCoords();
                this.canvas.renderAll();
            }
            else {
            }
        });
        this.canvas.on('mouse:up', (o) => {
            if (this.isInsertingCropRectangle == true) {
                debugger;
                console.log('mouse up done = ' + this.done);
                if (this.done) {
                    this.canvas.renderAll();
                    return;
                }
                this.isDown = false;
                this.crop_rect.set({
                    selectable: true
                });
                this.done = true;
            }
            else {
            }
        });
        this.canvas.on('selection:created', (event) => {
            console.log("canvas.on('selection:created'");
            this.selectionChanged(event);
        });
        this.canvas.on('selection:updated', (event) => {
            console.log("canvas.on('selection:updated'");
            this.selectionChanged(event);
        });
        // this.canvas.on("mouse:down", (event) =>{
        //     if (this.disabled) return;
        //     console.log("x",event.e.pageX-this.pos[0],this.pos[0],event.e.pageX,event.e.clientX,event.e.offsetX)
        //     const p=this.canvas.getPointer(event.e)
        //     console.log(p)
        //     this.clipPath.left = event.e.pageX-this.pos[0] ;
        //     this.clipPath.top =event.e.pageY - this.pos[1];
        //     //el.selectable = false;
        //     this.clipPath.visible = true;
        //     this.mousex = event.e.pageX;
        //     this.mousey = event.e.pageY;
        //     this.isCrop = true;
        //     this.canvas.bringToFront(this.clipPath);
        // });
        // this.canvas.on("mouse:move", (event)=> {
        //     //console.log(event);
        //     if (this.isCrop && !this.disabled) {
        //         if (event.e.pageX - this.mousex > 0) {
        //             this.clipPath.width = event.e.pageX - this.mousex;
        //         }
        //         if (event.e.pageY - this.mousey > 0) {
        //             this.clipPath.height = event.e.pageY - this.mousey;
        //         }
        //     }
        // });
        // this.canvas.on("mouse:up", (event) =>
        // {
        //     //var left = this.clipPath.left - object.left;
        //    // var top = this.clipPath.top - object.top;
        //    // left *= 1 / 0.25;
        //     //top *= 1 / 0.25;
        //    // var width = this.clipPath.width * 1 / 0.25;
        //     //var height = this.clipPath.height * 1 / 0.25;
        //     var clip=new fabric.Rect({absolutePositioned:true,top:this.clipPath.top,left:this.clipPath.left+this.clipPath.width,width:this.clipPath.width,height:this.clipPath.height})
        //     var clip1=new fabric.Rect({top:0,left:0,width:100,height:100})
        //     if(this.isCrop){
        //       //console.log(this.clipPath) .backgroundImage as fabric.Image).
        //     this.canvas.clipPath=clip
        //     //this.canvas.selectable = true;
        //       this.disabled = true;
        //       this.clipPath.visible = false;
        //       this.isCrop = false;
        //       this.setUndoRedo()
        //       this.canvas.renderAll();
        //     }
        // });
        //this.selectTool(this.currentTool);
        this.selectColor(this.currentColor);
        this.selectDrawingSize(this.currentSize);
        if (this.locale && i18nLanguages[this.locale.toLowerCase()]) {
            this.i18n = i18nLanguages[this.locale.toLowerCase()];
        }
        // FIXME remove after a while because properties are now deprecated
        if (this.saveBtnText) {
            this.i18n.saveBtn = this.saveBtnText;
        }
        if (this.cancelBtnText) {
            this.i18n.cancelBtn = this.cancelBtnText;
        }
        if (this.loadingText) {
            this.i18n.loading = this.loadingText;
        }
        if (this.errorText) {
            this.i18n.loadError = this.errorText;
        }
    }
    selectionChanged(event) {
        var _a, _b;
        console.log("selectionChanged");
        console.log("selectionChanged type = " + ((_a = event.target) === null || _a === void 0 ? void 0 : _a.type));
        switch ((_b = event.target) === null || _b === void 0 ? void 0 : _b.type) {
            case 'textbox':
                break;
            case 'image':
                this.lastSelectedPicture = event.target;
                break;
            case 'rect':
                break;
            case 'group':
                break;
            default:
                break;
        }
    }
    rescaleMask(target, mask) {
        mask.scaleX = 1;
        mask.scaleY = 1;
        mask.scaleX /= target.scaleX;
        mask.scaleY /= target.scaleY;
        const targetCenterX = target.width * target.scaleX / 2;
        const targetCenterY = target.height * target.scaleY / 2;
        const maskOverlapX = mask.left - target.left;
        const maskOverlapY = mask.top - target.top;
        let centerBasedX = maskOverlapX - targetCenterX;
        let centerBasedY = maskOverlapY - targetCenterY;
        if (maskOverlapX >= targetCenterX) {
            centerBasedX = (maskOverlapX - targetCenterX) / target.scaleX;
        }
        else {
            centerBasedX = (-(targetCenterX) + maskOverlapX) / target.scaleX;
        }
        if (maskOverlapY >= targetCenterY) {
            centerBasedY = (maskOverlapY - targetCenterY) / target.scaleY;
        }
        else {
            centerBasedY = (-(targetCenterY) + maskOverlapY) / target.scaleY;
        }
        console.log('targetleft = ' + target.left);
        console.log('targettop = ' + target.top);
        console.log('targetCenterX = ' + targetCenterX);
        console.log('targetCenterY = ' + targetCenterY);
        console.log('maskleft = ' + mask.left);
        console.log('masktop = ' + mask.top);
        console.log('maskOverlapX = ' + maskOverlapX);
        console.log('maskOverlapY = ' + maskOverlapY);
        console.log('centerBasedX = ' + centerBasedX);
        console.log('centerBasedY = ' + centerBasedY);
        mask.left = centerBasedX;
        mask.top = centerBasedY;
        mask.originX = 'left';
        mask.originY = 'top';
        mask.setCoords();
        mask.dirty = true;
        this.canvas.renderAll();
        //var newMask = mask;
        return (mask);
    }
    initClipPath() {
        this.clipPath = new fabric.Rect({
            //left: 100,
            //top: 100,
            fill: 'transparent',
            originX: 'left',
            originY: 'top',
            stroke: '#ccc',
            strokeDashArray: [2, 2],
            opacity: 1,
            width: 1,
            height: 1
        });
    }
    // Tools
    selectTool(tool) {
        this.currentTool = tool;
        if (this.currentTool === 'brush') {
            this.canvas.isDrawingMode = true;
        }
        else {
            this.canvas.isDrawingMode = false;
        }
    }
    selectDrawingSize(size) {
        this.currentSize = size;
        if (this.canvas) {
            this.canvas.freeDrawingBrush.width = this.drawingSizes[size];
        }
    }
    selectColor(color) {
        this.currentColor = color;
        if (this.canvas) {
            this.canvas.freeDrawingBrush.color = this.colors[color];
        }
    }
    maskC() {
        this.isInsertingCropRectangle = true;
        this.selectTool('mask');
        this.canvas.discardActiveObject();
        this.target.selectable = false;
        this.target.setCoords();
        this.target.dirty = true;
        //this.lastSelectedPicture.selectable = false;
        //this.lastSelectedPicture.setCoords();
        //this.lastSelectedPicture.dirty = true;
        this.canvas.renderAll();
        this.setUndoRedo();
        this.canvas.discardActiveObject();
        this.canvas.isDrawingMode = false;
    }
    // Actions
    crop() {
        if (this.target !== null && this.mask !== null && this.done) {
            this.selectTool('crop');
            this.target.setCoords();
            // Re-scale mask
            //this.mask = this.rescaleMask(this.target, this.mask);
            this.mask.setCoords();
            // Do the crop
            //this.target.clipPath = this.mask;
            //this.target.clipPath.setCoords();
            //this.target.dirty=true;
            //this.canvas.setActiveObject(this.target);
            //this.canvas.bringToFront(this.target);
            //this.target.clipPath.selectable = true;
            this.setUndoRedo();
            //this.stackUndoLocation.push(this.canvas.getObjects().length-2)
            //this.stackUndo.push(this.mask);
            this.canvas.remove(this.mask);
            this.canvas.renderAll();
            this.stackUndoLocation.push(this.canvas.getObjects().length - 1);
            this.stackUndo.push(this.imageUsed);
            this.setUndoRedo();
            const imageStr = this.canvas.toDataURL({
                width: this.crop_rect.width,
                height: this.crop_rect.height,
                left: this.crop_rect.left,
                top: this.crop_rect.top,
                format: 'jpeg'
            });
            this.canvas.remove(this.imageUsed);
            this.canvas.getObjects().forEach(e => e.opacity = 0);
            //this.canvas.getObjects()[0].opacity=1
            this.importPhotoFromSrc(imageStr);
            this.imageUsed.sendToBack();
            this.canvas.renderAll();
            this.setUndoRedo();
            console.log(this.target);
            this.isInsertingCropRectangle = false;
            this.done = false;
            this.selectTool('');
        }
        //this.disabled=false;
    }
    resize() {
        this.selectTool('resize');
        this.stackUndoLocation.push(this.canvas.getObjects().length - 1);
        this.stackUndo.push(this.imageUsed);
        this.setUndoRedo();
        const imageStr = this.canvas.toDataURL({
            format: 'jpeg'
        });
        this.canvas.remove(this.imageUsed);
        this.canvas.getObjects().forEach(e => e.opacity = 0);
        //this.canvas.getObjects()[0].opacity=1
        this.importPhotoFromSrc(imageStr, true);
        //this.canvas.setWidth(this.canvas.width+500)
        //this.canvas.setHeight(this.canvas.height+500)
        this.canvas.renderAll();
    }
    undo() {
        if (this.canUndo) {
            debugger;
            if (this.stackUndo.length > 0) {
                console.log(this.canvas.getObjects().length);
                if (this.canvas.getObjects().length - this.stackUndoLocation[this.stackUndoLocation.length - 1] > 1) {
                    const lastId = this.canvas.getObjects().length - 1;
                    const lastObj = this.canvas.getObjects()[lastId];
                    this.done = false;
                    this.stack.push(lastObj);
                    this.canvas.remove(lastObj);
                    this.setUndoRedo();
                    this.canvas.renderAll();
                }
                else {
                    const ob = this.stackUndo.pop();
                    const l = this.stackUndoLocation.pop();
                    if (ob instanceof fabric.Image) {
                        this.stack.push(this.imageUsed);
                        for (var i = l; i >= 0; i--) {
                            this.canvas.getObjects()[i].opacity = 1;
                        }
                        this.setUndoRedo();
                        this.canvas.remove(this.imageUsed);
                        this.importPhotoFromSrc(ob.getSrc());
                        debugger;
                    }
                    else {
                        this.canvas.add(ob);
                    }
                    this.canvas.renderAll();
                }
            }
            else {
                const lastId = this.canvas.getObjects().length - 1;
                const lastObj = this.canvas.getObjects()[lastId];
                this.done = false;
                this.stack.push(lastObj);
                this.canvas.remove(lastObj);
                this.setUndoRedo();
                this.canvas.renderAll();
            }
            //if(lastObj.canvas===undefined){
            // this.canvas.clipPath=null;
            // this.initClipPath()
            //this.clipPath=null;
            //}
        }
    }
    redo() {
        if (this.canRedo) {
            const firstInStack = this.stack.splice(-1, 1)[0];
            if (firstInStack) {
                if (firstInStack instanceof fabric.Image) {
                    this.stackUndoLocation.push(this.canvas.getObjects().length - 1);
                    this.stackUndo.push(this.imageUsed);
                    this.canvas.remove(this.imageUsed);
                    this.importPhotoFromSrc(firstInStack.getSrc());
                }
                else {
                    this.canvas.insertAt(firstInStack, this.canvas.getObjects().length, false);
                }
            }
            this.setUndoRedo();
        }
    }
    clearCanvas() {
        if (this.canvas) {
            this.canvas.clipPath = null;
            this.canvas.remove(...this.canvas.getObjects());
            //this.canvas.clear()
            this.setUndoRedo();
        }
    }
    saveImage() {
        if (!this.forceSizeExport || (this.forceSizeExport && this.width && this.height)) {
            const canvasScaledElement = document.createElement('canvas');
            const canvasScaled = new fabric.Canvas(canvasScaledElement);
            canvasScaled.backgroundColor = 'white';
            let imageStr = null;
            new Observable(observer => {
                if (this.imageUsed) {
                    if (this.target.clipPath) {
                        debugger;
                        imageStr = this.canvas.toDataURL({
                            width: this.target.clipPath.width,
                            height: this.target.clipPath.height,
                            left: this.target.clipPath.left + this.canvas.width / 2,
                            top: this.target.clipPath.top + this.canvas.height / 2,
                            format: 'jpeg'
                        });
                        console.log(imageStr);
                    }
                    if (this.forceSizeExport) {
                        canvasScaled.setWidth(this.width);
                        canvasScaled.setHeight(this.height);
                        this.imageUsed.cloneAsImage(imageCloned => {
                            imageCloned.scaleToWidth(this.width, false);
                            imageCloned.scaleToHeight(this.height, false);
                            canvasScaled.setBackgroundImage(imageCloned, (img) => {
                                if (!img) {
                                    observer.error(new Error('Impossible to draw the image on the temporary canvas'));
                                }
                                observer.next(canvasScaled);
                                observer.complete();
                            }, {
                                crossOrigin: 'anonymous',
                                originX: 'left',
                                originY: 'top'
                            });
                        });
                    }
                    else {
                        //canvasScaled.clipPath=this.mask
                        canvasScaled.setBackgroundImage(this.target, (img) => {
                            if (!img) {
                                observer.error(new Error('Impossible to draw the image on the temporary canvas'));
                            }
                            //canvasScaled.clipPath=this.clipPath
                            //(canvasScaled.backgroundImage as fabric.Image).clipPath=(this.canvas.backgroundImage as fabric.Image).clipPath
                            canvasScaled.setWidth(img.width * this.imageUsed.scaleX);
                            canvasScaled.setHeight(img.height * this.imageUsed.scaleY);
                            observer.next(canvasScaled);
                            observer.complete();
                        }, {
                            crossOrigin: 'anonymous',
                            originX: 'left',
                            originY: 'top'
                        });
                        //(canvasScaled.backgroundImage as fabric.Image).clipPath=this.clipPath
                    }
                }
                else {
                    canvasScaled.setWidth(this.width);
                    canvasScaled.setHeight(this.height);
                }
            }).pipe(switchMap(() => {
                let process = of(canvasScaled);
                if (this.canvas.getObjects().length > 1) {
                    this.canvas.remove(this.imageUsed);
                    const ratioX = canvasScaled.getWidth() / this.canvas.getWidth();
                    const ratioY = canvasScaled.getHeight() / this.canvas.getHeight();
                    this.canvas.getObjects().forEach((originalObject, i) => {
                        process = process.pipe(switchMap(() => {
                            return new Observable(observerObject => {
                                originalObject.clone((clonedObject) => {
                                    clonedObject.set('left', originalObject.left * ratioX);
                                    clonedObject.set('top', originalObject.top * ratioY);
                                    clonedObject.scaleToWidth(originalObject.width * ratioX);
                                    clonedObject.scaleToHeight(originalObject.height * ratioY);
                                    canvasScaled.insertAt(clonedObject, i, false);
                                    canvasScaled.renderAll();
                                    observerObject.next(canvasScaled);
                                    observerObject.complete();
                                });
                            });
                        }));
                    });
                }
                return process;
            })).subscribe(() => {
                canvasScaled.renderAll();
                // console.log(
                //     canvasScaled.toDataURL(
                //         {width:this.clipPath.width,
                //             height:this.clipPath.height,
                //             left:(this.canvas.backgroundImage as fabric.Image).clipPath.left,
                //             top:(this.canvas.backgroundImage as fabric.Image).clipPath.top,
                //             format:'jpeg'
                //         }))
                const im = canvasScaled.toDataURL({
                    format: 'jpeg'
                });
                console.log(im);
                canvasScaled.getElement().toBlob((data) => this.zone.run(() => {
                    this.save.emit(data);
                }), this.outputMimeType, this.outputQuality);
            });
        }
        else {
            this.canvas.getElement().toBlob((data) => this.zone.run(() => {
                this.save.emit(data);
            }), this.outputMimeType, this.outputQuality);
        }
    }
    cancelAction() {
        this.cancel.emit();
    }
    getTextTranslated(name) {
        let strOk = name.split('.').reduce((o, i) => o[i], this.i18n);
        if (this.i18nUser) {
            try {
                const str = name.split('.').reduce((o, i) => o[i], this.i18nUser);
                if (str) {
                    strOk = str;
                }
            }
            catch (e) {
                // if we pass here, ignored
            }
        }
        if (!strOk) {
            console.error(name + ' translation not found !');
        }
        return strOk;
    }
    getTooltipTranslated(name) {
        if (this.enableTooltip) {
            return this.getTextTranslated(name);
        }
        else {
            return '';
        }
    }
    setUndoRedo() {
        this.canUndo = this.canvas.getObjects().length > 1 || this.stackUndo.length > 0;
        this.canRedo = this.stack.length > 0;
        // this.canvas.renderAll();
    }
    importPhotoFromFile(event) {
        if (event.target.files && event.target.files.length > 0) {
            const file = event.target.files[0];
            if (file.type.match('image.*')) {
                this.importPhotoFromBlob(file);
            }
            else {
                throw new Error('Not an image !');
            }
        }
    }
    removeImage() {
        if (this.imageUsed) {
            this.imageUsed.dispose();
            this.imageUsed = null;
        }
        this.canvas.backgroundImage = null;
        if (this.width && this.height) {
            this.canvas.setWidth(this.width);
            this.canvas.setHeight(this.height);
        }
        this.canvas.renderAll();
    }
    get hasImage() {
        return !!this.canvas.backgroundImage;
    }
    importPhotoFromSrc(src, select = false, stackundo = false) {
        this.isLoading = true;
        let isFirstTry = true;
        const imgEl = new Image();
        imgEl.setAttribute('crossorigin', 'anonymous');
        imgEl.crossOrigin = "anonymous";
        imgEl.src = src;
        imgEl.onerror = () => {
            // Retry with cors proxy
            /* if (isFirstTry) {
                 imgEl.src = 'https://cors-anywhere.herokuapp.com/' + this.src;
                 isFirstTry = false;
             }
              else */
            {
                this.isLoading = false;
                this.hasError = true;
                this.errorMessage = this.getTextTranslated('loadError').replace('%@', this.src);
            }
        };
        console.log(imgEl);
        imgEl.onload = () => {
            this.isLoading = false;
            this.imageUsed = new fabric.Image(imgEl, {
                selectable: false,
                width: imgEl.width,
                height: imgEl.height
            });
            this.canvas.insertAt(this.imageUsed, 0, false);
            //this.canvas.sendToBack(this.imageUsed)
            this.canvas.width = imgEl.width;
            this.canvas.height = imgEl.height;
            //this.canvas.setActiveObject(this.imageUsed)
            console.log(this.imageUsed);
            this.imageUsed.cloneAsImage(image => {
                let width = imgEl.width;
                let height = imgEl.height;
                if (this.width && this.width < width) {
                    width = this.width;
                }
                if (this.height && this.height < height) {
                    height = this.height;
                }
                this.imageUsed.scaleToWidth(width);
                this.imageUsed.scaleToHeight(height);
                image.scaleToWidth(width, false);
                image.scaleToHeight(height, false);
                console.log(image);
                // this.canvas.setBackgroundImage(image, ((img: HTMLImageElement) => {
                //   if (img) {
                if (this.forceSizeCanvas) {
                    this.canvas.setWidth(width);
                    this.canvas.setHeight(height);
                }
                else {
                    this.canvas.setWidth(image.getScaledWidth());
                    this.canvas.setHeight(image.getScaledHeight());
                }
                //  }
                // }), {
                //   crossOrigin: 'Anonymous',
                //   originX: 'left',
                //    originY: 'top'
                //});
                this.target = this.imageUsed;
                this.target.selectable = select;
                if (select) {
                    this.target.lockMovementX = true;
                    this.target.lockMovementY = true;
                    this.canvas.setWidth(width + 500);
                    this.canvas.setHeight(height + 500);
                }
                if (stackundo) {
                    this.stackUndoLocation.push(this.canvas.getObjects().length - 1);
                    this.stackUndo.push(this.imageUsed);
                    this.setUndoRedo();
                }
            });
        };
    }
    importPhotoFromBlob(file) {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = (evtReader) => {
            if (evtReader.target.readyState == FileReader.DONE) {
                this.importPhotoFromSrc(evtReader.target.result);
            }
        };
    }
    importPhotoFromUrl() {
        const url = prompt(this.getTooltipTranslated('loadImageUrl'));
        if (url) {
            this.importPhotoFromSrc(url);
        }
    }
    ngOnChanges(changes) {
        if (changes.src && !changes.src.firstChange && changes.src.currentValue) {
            if (typeof changes.src.currentValue === 'string') {
                this.importPhotoFromSrc(changes.src.currentValue);
            }
            else if (changes.src.currentValue) {
                this.importPhotoFromBlob(changes.src.currentValue);
            }
        }
    }
}
ImageDrawingComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: ImageDrawingComponent, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
ImageDrawingComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: ImageDrawingComponent, selector: "image-drawing", inputs: { src: "src", width: "width", height: "height", saveBtnClass: "saveBtnClass", cancelBtnClass: "cancelBtnClass", forceSizeCanvas: "forceSizeCanvas", forceSizeExport: "forceSizeExport", enableRemoveImage: "enableRemoveImage", enableLoadAnotherImage: "enableLoadAnotherImage", enableTooltip: "enableTooltip", showCancelButton: "showCancelButton", i18nUser: ["i18n", "i18nUser"], locale: "locale", saveBtnText: "saveBtnText", cancelBtnText: "cancelBtnText", loadingText: "loadingText", errorText: "errorText", loadingTemplate: "loadingTemplate", errorTemplate: "errorTemplate", outputMimeType: "outputMimeType", outputQuality: "outputQuality", borderCss: "borderCss", drawingSizes: "drawingSizes", colors: "colors" }, outputs: { save: "save", cancel: "cancel" }, usesOnChanges: true, ngImport: i0, template: "\r\n\r\n<div class=\"loading\" *ngIf=\"isLoading\">\r\n  <ng-container *ngTemplateOutlet=\"loadingTemplate ? loadingTemplate : defaultLoading\"></ng-container>\r\n</div>\r\n<div class=\"error\" *ngIf=\"hasError\">\r\n  <ng-container *ngTemplateOutlet=\"errorTemplate ? errorTemplate : defaultError\"></ng-container>\r\n</div>\r\n\r\n<ng-template #defaultLoading><p>{{ getTextTranslated('loading') }}</p></ng-template>\r\n<ng-template #defaultError> <p>{{ errorMessage }}</p> </ng-template>\r\n\r\n<div [ngStyle]=\"{ border: borderCss }\">\r\n  <canvas id=\"canvas\"></canvas>\r\n</div>\r\n<div class=\"toolbar\" *ngIf=\"!isLoading\">\r\n  <div class=\"tools\">\r\n      <div class=\"row1\">\r\n          <i class=\"material-icons btn1\" [class.selected]=\"currentTool === 'brush'\" (click)=\"selectTool('brush')\"\r\n             [title]=\"getTooltipTranslated('tools.brush')\">brush</i>\r\n          <span *ngFor=\"let drawingSizeName of drawingSizesName\" class=\"size btn1\"\r\n                [style.width.px]=\"drawingSizes[drawingSizeName] * 0.8 + 8\"\r\n                [style.height.px]=\"drawingSizes[drawingSizeName] * 0.8 + 8\"\r\n                [style.borderRadius.px]=\"drawingSizes[drawingSizeName] * 0.4 + 4\"\r\n                [class.selected]=\"currentSize == drawingSizeName\"\r\n                [title]=\"getTooltipTranslated('sizes.' + drawingSizeName)\"\r\n                (click)=\"selectDrawingSize(drawingSizeName)\">\r\n    </span>\r\n\r\n          <input style=\"display: none\" type=\"file\" #fileInput (change)=\"importPhotoFromFile($event)\"\r\n                 accept=\"image/*\"/>\r\n          <i class=\"material-icons btn1\" *ngIf=\"enableLoadAnotherImage && !hasImage\" (click)=\"fileInput.click();\"\r\n             [title]=\"getTooltipTranslated('loadImage')\">attach_file</i>\r\n          <i class=\"material-icons btn1\" *ngIf=\"enableLoadAnotherImage && !hasImage\" (click)=\"importPhotoFromUrl()\"\r\n             [title]=\"getTooltipTranslated('loadImageUrl')\">insert_drive_file</i>\r\n          <i class=\"material-icons btn1\" *ngIf=\"enableRemoveImage && hasImage\" (click)=\"removeImage()\"\r\n             [title]=\"getTooltipTranslated('removeImage')\">clear</i>\r\n\r\n             <i class=\"material-icons btn1\"  [class.selected]=\"currentTool === 'crop' || done===false\" (click)=\"crop()\"\r\n             [title]=\"getTooltipTranslated('crop')\">crop</i>\r\n             <i class=\"material-icons btn1\"  [class.selected]=\"currentTool === 'mask'\" (click)=\"maskC()\"\r\n             [title]=\"getTooltipTranslated('mask')\">crop_free</i>\r\n             <i class=\"material-icons btn1\" [class.selected]=\"currentTool === 'resize'\" (click)=\"resize()\"\r\n             [title]=\"getTooltipTranslated('resize')\">expand</i>\r\n          <i class=\"material-icons btn1\" [class.disabled]=\"!canUndo\" (click)=\"undo()\"\r\n             [title]=\"getTooltipTranslated('undo')\">undo</i>\r\n          <i class=\"material-icons btn1\" [class.disabled]=\"!canRedo\" (click)=\"redo()\"\r\n             [title]=\"getTooltipTranslated('redo')\">redo</i>\r\n          <!-- <i class=\"material-icons btn1\" (click)=\"clearCanvas()\" [title]=\"getTooltipTranslated('clear')\">delete</i> -->\r\n      </div>\r\n      <div class=\"row1\">\r\n          <div *ngFor=\"let colorName of colorsName\" [class.selected]=\"currentColor === colorName\" class=\"color\"\r\n               [ngClass]=\"colorName\"\r\n               [style.background]=\"colors[colorName]\" [title]=\"getTooltipTranslated('colors.' + colorName)\"\r\n               (click)=\"selectColor(colorName)\">\r\n          </div>\r\n      </div>\r\n  </div>\r\n\r\n  <!-- Any additional toolbar buttons to be projected by the consuming app -->\r\n  <ng-content></ng-content>\r\n</div>\r\n<div class=\"buttons\" *ngIf=\"!isLoading\">\r\n\r\n    <a href=\"#\" [class]=\"cancelBtnClass\" *ngIf=\"showCancelButton\"\r\n       (click)=\"cancelAction(); $event.preventDefault()\">{{ getTextTranslated('cancelBtn') }}</a>\r\n       <button  [class]=\"saveBtnClass\"\r\n       (click)=\"saveImage()\">{{ getTextTranslated('saveBtn') }}</button>\r\n    </div>\r\n", styles: [":host{display:flex;flex-direction:column;align-items:center}:host .toolbar{display:flex;flex-direction:column;justify-content:space-between;align-items:center}:host .tools{display:inline-flex;flex-direction:column;padding:20px;margin:10px;background:#fff;border-radius:6px;box-shadow:0 3px 10px #0006}:host .row1{display:flex;width:300px;justify-content:space-around;align-items:center}:host .row1:first-child{margin-bottom:10px}:host .btn1{cursor:pointer}:host .btn1.selected{color:#bdbdbd}:host .btn1.disabled{cursor:initial;color:#bdbdbd}:host .size{background-color:#000}:host .size.selected{background-color:#bdbdbd}:host .color{width:28px;height:28px;border-radius:14px;cursor:pointer;display:flex;align-items:center;justify-content:center}:host .color.selected:after{content:\"\";width:10px;height:10px;background:#000;display:flex;border-radius:5px}:host .color.black{background-color:#000}:host .color.black.selected:after{background:#fff}:host .color.white{border:1px solid #a7a7a7}:host .buttons{width:80%;margin:10px;display:flex;flex-direction:row;justify-content:flex-end}:host .button{cursor:pointer;outline:0;border:none;white-space:nowrap;text-decoration:none;vertical-align:baseline;text-align:center;min-width:64px;line-height:36px;padding:3px 16px;border-radius:4px;overflow:visible;transition:background .4s cubic-bezier(.25,.8,.25,1),box-shadow .28s cubic-bezier(.4,0,.2,1);margin:10px}:host .button:hover{text-decoration:none!important}:host .button.btn-primary{background-color:#ef5f27;color:#fff}:host .button.btn-primary:hover{background-color:#ef5f27cc}:host .button.btn-light{color:#ef5f27}:host .button.btn-light:hover{background-color:#ef5f271a}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: ImageDrawingComponent, decorators: [{
            type: Component,
            args: [{ selector: 'image-drawing', template: "\r\n\r\n<div class=\"loading\" *ngIf=\"isLoading\">\r\n  <ng-container *ngTemplateOutlet=\"loadingTemplate ? loadingTemplate : defaultLoading\"></ng-container>\r\n</div>\r\n<div class=\"error\" *ngIf=\"hasError\">\r\n  <ng-container *ngTemplateOutlet=\"errorTemplate ? errorTemplate : defaultError\"></ng-container>\r\n</div>\r\n\r\n<ng-template #defaultLoading><p>{{ getTextTranslated('loading') }}</p></ng-template>\r\n<ng-template #defaultError> <p>{{ errorMessage }}</p> </ng-template>\r\n\r\n<div [ngStyle]=\"{ border: borderCss }\">\r\n  <canvas id=\"canvas\"></canvas>\r\n</div>\r\n<div class=\"toolbar\" *ngIf=\"!isLoading\">\r\n  <div class=\"tools\">\r\n      <div class=\"row1\">\r\n          <i class=\"material-icons btn1\" [class.selected]=\"currentTool === 'brush'\" (click)=\"selectTool('brush')\"\r\n             [title]=\"getTooltipTranslated('tools.brush')\">brush</i>\r\n          <span *ngFor=\"let drawingSizeName of drawingSizesName\" class=\"size btn1\"\r\n                [style.width.px]=\"drawingSizes[drawingSizeName] * 0.8 + 8\"\r\n                [style.height.px]=\"drawingSizes[drawingSizeName] * 0.8 + 8\"\r\n                [style.borderRadius.px]=\"drawingSizes[drawingSizeName] * 0.4 + 4\"\r\n                [class.selected]=\"currentSize == drawingSizeName\"\r\n                [title]=\"getTooltipTranslated('sizes.' + drawingSizeName)\"\r\n                (click)=\"selectDrawingSize(drawingSizeName)\">\r\n    </span>\r\n\r\n          <input style=\"display: none\" type=\"file\" #fileInput (change)=\"importPhotoFromFile($event)\"\r\n                 accept=\"image/*\"/>\r\n          <i class=\"material-icons btn1\" *ngIf=\"enableLoadAnotherImage && !hasImage\" (click)=\"fileInput.click();\"\r\n             [title]=\"getTooltipTranslated('loadImage')\">attach_file</i>\r\n          <i class=\"material-icons btn1\" *ngIf=\"enableLoadAnotherImage && !hasImage\" (click)=\"importPhotoFromUrl()\"\r\n             [title]=\"getTooltipTranslated('loadImageUrl')\">insert_drive_file</i>\r\n          <i class=\"material-icons btn1\" *ngIf=\"enableRemoveImage && hasImage\" (click)=\"removeImage()\"\r\n             [title]=\"getTooltipTranslated('removeImage')\">clear</i>\r\n\r\n             <i class=\"material-icons btn1\"  [class.selected]=\"currentTool === 'crop' || done===false\" (click)=\"crop()\"\r\n             [title]=\"getTooltipTranslated('crop')\">crop</i>\r\n             <i class=\"material-icons btn1\"  [class.selected]=\"currentTool === 'mask'\" (click)=\"maskC()\"\r\n             [title]=\"getTooltipTranslated('mask')\">crop_free</i>\r\n             <i class=\"material-icons btn1\" [class.selected]=\"currentTool === 'resize'\" (click)=\"resize()\"\r\n             [title]=\"getTooltipTranslated('resize')\">expand</i>\r\n          <i class=\"material-icons btn1\" [class.disabled]=\"!canUndo\" (click)=\"undo()\"\r\n             [title]=\"getTooltipTranslated('undo')\">undo</i>\r\n          <i class=\"material-icons btn1\" [class.disabled]=\"!canRedo\" (click)=\"redo()\"\r\n             [title]=\"getTooltipTranslated('redo')\">redo</i>\r\n          <!-- <i class=\"material-icons btn1\" (click)=\"clearCanvas()\" [title]=\"getTooltipTranslated('clear')\">delete</i> -->\r\n      </div>\r\n      <div class=\"row1\">\r\n          <div *ngFor=\"let colorName of colorsName\" [class.selected]=\"currentColor === colorName\" class=\"color\"\r\n               [ngClass]=\"colorName\"\r\n               [style.background]=\"colors[colorName]\" [title]=\"getTooltipTranslated('colors.' + colorName)\"\r\n               (click)=\"selectColor(colorName)\">\r\n          </div>\r\n      </div>\r\n  </div>\r\n\r\n  <!-- Any additional toolbar buttons to be projected by the consuming app -->\r\n  <ng-content></ng-content>\r\n</div>\r\n<div class=\"buttons\" *ngIf=\"!isLoading\">\r\n\r\n    <a href=\"#\" [class]=\"cancelBtnClass\" *ngIf=\"showCancelButton\"\r\n       (click)=\"cancelAction(); $event.preventDefault()\">{{ getTextTranslated('cancelBtn') }}</a>\r\n       <button  [class]=\"saveBtnClass\"\r\n       (click)=\"saveImage()\">{{ getTextTranslated('saveBtn') }}</button>\r\n    </div>\r\n", styles: [":host{display:flex;flex-direction:column;align-items:center}:host .toolbar{display:flex;flex-direction:column;justify-content:space-between;align-items:center}:host .tools{display:inline-flex;flex-direction:column;padding:20px;margin:10px;background:#fff;border-radius:6px;box-shadow:0 3px 10px #0006}:host .row1{display:flex;width:300px;justify-content:space-around;align-items:center}:host .row1:first-child{margin-bottom:10px}:host .btn1{cursor:pointer}:host .btn1.selected{color:#bdbdbd}:host .btn1.disabled{cursor:initial;color:#bdbdbd}:host .size{background-color:#000}:host .size.selected{background-color:#bdbdbd}:host .color{width:28px;height:28px;border-radius:14px;cursor:pointer;display:flex;align-items:center;justify-content:center}:host .color.selected:after{content:\"\";width:10px;height:10px;background:#000;display:flex;border-radius:5px}:host .color.black{background-color:#000}:host .color.black.selected:after{background:#fff}:host .color.white{border:1px solid #a7a7a7}:host .buttons{width:80%;margin:10px;display:flex;flex-direction:row;justify-content:flex-end}:host .button{cursor:pointer;outline:0;border:none;white-space:nowrap;text-decoration:none;vertical-align:baseline;text-align:center;min-width:64px;line-height:36px;padding:3px 16px;border-radius:4px;overflow:visible;transition:background .4s cubic-bezier(.25,.8,.25,1),box-shadow .28s cubic-bezier(.4,0,.2,1);margin:10px}:host .button:hover{text-decoration:none!important}:host .button.btn-primary{background-color:#ef5f27;color:#fff}:host .button.btn-primary:hover{background-color:#ef5f27cc}:host .button.btn-light{color:#ef5f27}:host .button.btn-light:hover{background-color:#ef5f271a}\n"] }]
        }], ctorParameters: function () { return [{ type: i0.NgZone }]; }, propDecorators: { src: [{
                type: Input
            }], width: [{
                type: Input
            }], height: [{
                type: Input
            }], saveBtnClass: [{
                type: Input
            }], cancelBtnClass: [{
                type: Input
            }], forceSizeCanvas: [{
                type: Input
            }], forceSizeExport: [{
                type: Input
            }], enableRemoveImage: [{
                type: Input
            }], enableLoadAnotherImage: [{
                type: Input
            }], enableTooltip: [{
                type: Input
            }], showCancelButton: [{
                type: Input
            }], i18nUser: [{
                type: Input,
                args: ['i18n']
            }], locale: [{
                type: Input
            }], saveBtnText: [{
                type: Input
            }], cancelBtnText: [{
                type: Input
            }], loadingText: [{
                type: Input
            }], errorText: [{
                type: Input
            }], loadingTemplate: [{
                type: Input
            }], errorTemplate: [{
                type: Input
            }], outputMimeType: [{
                type: Input
            }], outputQuality: [{
                type: Input
            }], borderCss: [{
                type: Input
            }], drawingSizes: [{
                type: Input
            }], colors: [{
                type: Input
            }], save: [{
                type: Output
            }], cancel: [{
                type: Output
            }] } });

class ImageDrawingModule {
}
ImageDrawingModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: ImageDrawingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
ImageDrawingModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: ImageDrawingModule, declarations: [ImageDrawingComponent], imports: [CommonModule,
        MatIconModule], exports: [ImageDrawingComponent] });
ImageDrawingModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: ImageDrawingModule, imports: [CommonModule,
        MatIconModule] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: ImageDrawingModule, decorators: [{
            type: NgModule,
            args: [{
                    declarations: [
                        ImageDrawingComponent
                    ],
                    exports: [
                        ImageDrawingComponent,
                    ],
                    imports: [
                        CommonModule,
                        MatIconModule
                    ]
                }]
        }] });

/*
 * Public API Surface of ngx-image-drawing-zone
 */

/**
 * Generated bundle index. Do not edit.
 */

export { I18nEn, I18nFr, I18nHe, ImageDrawingComponent, ImageDrawingModule, i18nLanguages };
//# sourceMappingURL=ngx-image-drawing-zone.mjs.map