ngx-image-drawing-sixteen
Version:

1,012 lines • 52.7 kB
JavaScript
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