UNPKG

@bitforgehq/angular-ionic-image-cropper

Version:

An Ionic Angular library for cross platform image cropping.

1 lines 13.7 kB
{"version":3,"file":"bitforgehq-angular-ionic-image-cropper.mjs","sources":["../../../projects/angular-ionic-image-cropper/src/lib/angular-ionic-image-cropper.component.ts","../../../projects/angular-ionic-image-cropper/src/lib/angular-ionic-image-cropper.service.ts","../../../projects/angular-ionic-image-cropper/src/public-api.ts","../../../projects/angular-ionic-image-cropper/src/bitforgehq-angular-ionic-image-cropper.ts"],"sourcesContent":["import { Component, ElementRef, Input, Output, EventEmitter, ViewChild, AfterViewInit, Inject, ViewEncapsulation } from '@angular/core';\nimport { ModalController } from '@ionic/angular/standalone';\nimport Cropper from 'cropperjs';\n\n@Component({\n selector: 'lib-angular-ionic-image-cropper',\n template: `\n <div class=\"lib-cropper-modal-container\">\n <div class=\"lib-cropper-content\">\n <div class=\"lib-cropper-container\" #cropperContainer>\n <img\n #imageElement\n [src]=\"imageUrl\"\n crossorigin=\"anonymous\"\n style=\"max-width: 100%; object-fit: contain; display: block;\"\n />\n </div>\n </div>\n\n <div class=\"lib-cropper-footer\">\n <div class=\"lib-cropper-actions ios-footer\">\n <button class=\"btn btn-cancel\" (click)=\"cancel()\">{{ cancelText }}</button>\n <button class=\"btn btn-crop\" (click)=\"crop()\">{{ doneText }}</button>\n </div>\n </div>\n </div>\n `,\n styleUrls: ['./styles.scss'],\n encapsulation: ViewEncapsulation.None,\n standalone: true\n})\nexport class ImageCropperComponent implements AfterViewInit {\n @Input() imageUrl!: string;\n @Input() aspectRatio: number = 16 / 9;\n @Input() cancelText: string = 'Cancel';\n @Input() doneText: string = 'Done';\n @Input() quality: number = 0.9;\n @Input() outputFormat: 'image/jpeg' | 'image/png' | 'image/webp' = 'image/jpeg';\n @Output() cropComplete = new EventEmitter<Blob>();\n\n @ViewChild('imageElement') imageElement!: ElementRef<HTMLImageElement>;\n @ViewChild('cropperContainer') cropperContainer!: ElementRef<HTMLDivElement>;\n private cropper!: Cropper;\n\n constructor(@Inject(ModalController) private modalCtrl: ModalController) { }\n\n ngAfterViewInit() {\n const imgEl = this.imageElement.nativeElement;\n const containerEl = this.cropperContainer.nativeElement;\n\n containerEl.style.width = '100%';\n containerEl.style.height = '100%';\n containerEl.style.overflow = 'hidden';\n\n const initWhenReady = () => {\n requestAnimationFrame(() => {\n const width = imgEl.naturalWidth;\n const height = imgEl.naturalHeight;\n\n if (width >= 300 && height >= 200) {\n // Force layout + redraw tricks\n imgEl.style.display = 'none';\n setTimeout(() => {\n imgEl.style.display = 'block';\n window.dispatchEvent(new Event('resize'));\n\n this.initializeCropper();\n }, 20);\n } else {\n setTimeout(initWhenReady, 50);\n }\n });\n };\n\n if (imgEl.complete) {\n initWhenReady();\n } else {\n imgEl.onload = () => initWhenReady();\n }\n }\n\n private initializeCropper() {\n this.cropper = new Cropper(this.imageElement.nativeElement, {\n aspectRatio: this.aspectRatio,\n viewMode: 1,\n autoCropArea: 0.8,\n responsive: true,\n restore: false,\n center: true,\n highlight: false,\n cropBoxMovable: true,\n cropBoxResizable: true,\n toggleDragModeOnDblclick: false,\n ready: () => {\n const bg = document.querySelector('.cropper-bg') as HTMLElement;\n if (bg) {\n bg.style.backgroundImage = 'none';\n } else {\n setTimeout(() => {\n const retry = document.querySelector('.cropper-bg') as HTMLElement;\n if (retry) retry.style.backgroundImage = 'none';\n }, 200);\n }\n }\n });\n }\n\n crop() {\n this.getCroppedImage().then((blob) => {\n this.modalCtrl.dismiss(blob);\n });\n }\n\n cancel() {\n this.modalCtrl.dismiss();\n }\n\n getCroppedImage(): Promise<Blob> {\n return new Promise((resolve) => {\n const canvas = this.cropper.getCroppedCanvas();\n canvas.toBlob((blob: Blob | null) => {\n if (blob) this.cropComplete.emit(blob);\n resolve(blob!);\n this.modalCtrl.dismiss(blob);\n }, this.outputFormat, this.quality);\n });\n }\n}\n","// projects/image-cropper/src/lib/image-cropper.service.ts\nimport { Injectable } from '@angular/core';\nimport { Camera, CameraResultType, CameraSource } from '@capacitor/camera';\nimport { ModalController } from '@ionic/angular/standalone';\nimport { ImageCropperComponent } from './angular-ionic-image-cropper.component';\n\n/**\n * Configuration options for the image cropper\n */\nexport interface ImageCropperConfig {\n /**\n * Text to display on the cancel button\n * @default 'Cancel'\n */\n cancelText?: string;\n \n /**\n * Text to display on the done/confirm button\n * @default 'Done'\n */\n doneText?: string;\n \n /**\n * Aspect ratio for the crop area (width / height)\n * Common values: 1 (square), 16/9 (widescreen), 4/3 (standard)\n * @default 16/9\n */\n aspectRatio?: number;\n \n /**\n * Quality of the output image (0.1 to 1.0)\n * @default 0.9\n */\n quality?: number;\n \n /**\n * Output format for the cropped image\n * @default 'image/jpeg'\n */\n outputFormat?: 'image/jpeg' | 'image/png' | 'image/webp';\n}\n\n/**\n * Service for handling image cropping operations with Ionic integration\n */\n@Injectable()\nexport class ImageCropperService {\n constructor(private modalCtrl: ModalController) { }\n\n /**\n * Opens the image cropper modal with the specified image\n * @param imagePath - Path or URL to the image to crop\n * @param config - Configuration options for the cropper\n * @returns Promise that resolves to the cropped image as a Blob\n * @throws Error if the crop operation is cancelled\n */\n async openCropper(imagePath: string, config: ImageCropperConfig = {}): Promise<Blob> {\n const {\n cancelText = 'Cancel',\n doneText = 'Done',\n aspectRatio = 16 / 9,\n quality = 0.9,\n outputFormat = 'image/jpeg'\n } = config;\n\n const modal = await this.modalCtrl.create({\n component: ImageCropperComponent,\n componentProps: {\n imageUrl: imagePath,\n aspectRatio,\n cancelText,\n doneText,\n quality,\n outputFormat,\n modalCtrl: this.modalCtrl,\n },\n cssClass: 'full-height-modal',\n });\n\n await modal.present();\n const { data } = await modal.onWillDismiss();\n\n if (!data) throw new Error('Crop cancelled');\n return data;\n }\n\n /**\n * Takes a photo using the device camera and opens the cropper\n * @param config - Configuration options for the cropper\n * @returns Promise that resolves to the cropped image as a Blob\n * @throws Error if photo capture or crop operation fails\n */\n async takeAndCropPhoto(config: ImageCropperConfig = {}): Promise<Blob> {\n try {\n const photo = await Camera.getPhoto({\n quality: 90,\n resultType: CameraResultType.Uri,\n source: CameraSource.Camera,\n allowEditing: false,\n });\n\n // Use webPath for web environments, fallback to path for native\n const imagePath = photo.webPath || photo.path;\n \n if (!imagePath) {\n throw new Error('Failed to capture photo - no image path available');\n }\n\n return this.openCropper(imagePath, config);\n } catch (error) {\n console.error('Error in takeAndCropPhoto:', error);\n throw error;\n }\n }\n}","/*\n * Public API Surface of angular-ionic-image-cropper\n */\n\nexport * from './lib/angular-ionic-image-cropper.component';\nexport * from './lib/angular-ionic-image-cropper.service';\n\n// Export styles for manual import if needed\nexport const STYLES = './styles.scss';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;;MA+Ba,qBAAqB,CAAA;AAaa,IAAA,SAAA;AAZpC,IAAA,QAAQ;AACR,IAAA,WAAW,GAAW,EAAE,GAAG,CAAC;IAC5B,UAAU,GAAW,QAAQ;IAC7B,QAAQ,GAAW,MAAM;IACzB,OAAO,GAAW,GAAG;IACrB,YAAY,GAA8C,YAAY;AACrE,IAAA,YAAY,GAAG,IAAI,YAAY,EAAQ;AAEtB,IAAA,YAAY;AACR,IAAA,gBAAgB;AACvC,IAAA,OAAO;AAEf,IAAA,WAAA,CAA6C,SAA0B,EAAA;QAA1B,IAAA,CAAA,SAAS,GAAT,SAAS;;IAEtD,eAAe,GAAA;AACb,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,aAAa;AAC7C,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,gBAAgB,CAAC,aAAa;AAEvD,QAAA,WAAW,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM;AAChC,QAAA,WAAW,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM;AACjC,QAAA,WAAW,CAAC,KAAK,CAAC,QAAQ,GAAG,QAAQ;QAErC,MAAM,aAAa,GAAG,MAAK;YACzB,qBAAqB,CAAC,MAAK;AACzB,gBAAA,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY;AAChC,gBAAA,MAAM,MAAM,GAAG,KAAK,CAAC,aAAa;gBAElC,IAAI,KAAK,IAAI,GAAG,IAAI,MAAM,IAAI,GAAG,EAAE;;AAEjC,oBAAA,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM;oBAC5B,UAAU,CAAC,MAAK;AACd,wBAAA,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,OAAO;wBAC7B,MAAM,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC;wBAEzC,IAAI,CAAC,iBAAiB,EAAE;qBACzB,EAAE,EAAE,CAAC;;qBACD;AACL,oBAAA,UAAU,CAAC,aAAa,EAAE,EAAE,CAAC;;AAEjC,aAAC,CAAC;AACJ,SAAC;AAED,QAAA,IAAI,KAAK,CAAC,QAAQ,EAAE;AAClB,YAAA,aAAa,EAAE;;aACV;YACL,KAAK,CAAC,MAAM,GAAG,MAAM,aAAa,EAAE;;;IAIhC,iBAAiB,GAAA;QACvB,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,aAAa,EAAE;YAC1D,WAAW,EAAE,IAAI,CAAC,WAAW;AAC7B,YAAA,QAAQ,EAAE,CAAC;AACX,YAAA,YAAY,EAAE,GAAG;AACjB,YAAA,UAAU,EAAE,IAAI;AAChB,YAAA,OAAO,EAAE,KAAK;AACd,YAAA,MAAM,EAAE,IAAI;AACZ,YAAA,SAAS,EAAE,KAAK;AAChB,YAAA,cAAc,EAAE,IAAI;AACpB,YAAA,gBAAgB,EAAE,IAAI;AACtB,YAAA,wBAAwB,EAAE,KAAK;YAC/B,KAAK,EAAE,MAAK;gBACV,MAAM,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAgB;gBAC/D,IAAI,EAAE,EAAE;AACN,oBAAA,EAAE,CAAC,KAAK,CAAC,eAAe,GAAG,MAAM;;qBAC5B;oBACL,UAAU,CAAC,MAAK;wBACd,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAgB;AAClE,wBAAA,IAAI,KAAK;AAAE,4BAAA,KAAK,CAAC,KAAK,CAAC,eAAe,GAAG,MAAM;qBAChD,EAAE,GAAG,CAAC;;;AAGZ,SAAA,CAAC;;IAGJ,IAAI,GAAA;QACF,IAAI,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,KAAI;AACnC,YAAA,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC;AAC9B,SAAC,CAAC;;IAGJ,MAAM,GAAA;AACJ,QAAA,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE;;IAG1B,eAAe,GAAA;AACb,QAAA,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,KAAI;YAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE;AAC9C,YAAA,MAAM,CAAC,MAAM,CAAC,CAAC,IAAiB,KAAI;AAClC,gBAAA,IAAI,IAAI;AAAE,oBAAA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;gBACtC,OAAO,CAAC,IAAK,CAAC;AACd,gBAAA,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC;aAC7B,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC;AACrC,SAAC,CAAC;;AA9FO,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,kBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,qBAAqB,kBAaZ,eAAe,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAbxB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,qBAAqB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iCAAA,EAAA,MAAA,EAAA,EAAA,QAAA,EAAA,UAAA,EAAA,WAAA,EAAA,aAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,UAAA,EAAA,OAAA,EAAA,SAAA,EAAA,YAAA,EAAA,cAAA,EAAA,EAAA,OAAA,EAAA,EAAA,YAAA,EAAA,cAAA,EAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,cAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,cAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,EAAA,YAAA,EAAA,kBAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,kBAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAzBtB;;;;;;;;;;;;;;;;;;;;AAoBT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,8iKAAA,CAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FAKU,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBA3BjC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,iCAAiC,EAAA,QAAA,EACjC;;;;;;;;;;;;;;;;;;;;AAoBT,EAAA,CAAA,EAAA,aAAA,EAEc,iBAAiB,CAAC,IAAI,EAAA,UAAA,EACzB,IAAI,EAAA,MAAA,EAAA,CAAA,8iKAAA,CAAA,EAAA;;0BAeH,MAAM;2BAAC,eAAe;yCAZ1B,QAAQ,EAAA,CAAA;sBAAhB;gBACQ,WAAW,EAAA,CAAA;sBAAnB;gBACQ,UAAU,EAAA,CAAA;sBAAlB;gBACQ,QAAQ,EAAA,CAAA;sBAAhB;gBACQ,OAAO,EAAA,CAAA;sBAAf;gBACQ,YAAY,EAAA,CAAA;sBAApB;gBACS,YAAY,EAAA,CAAA;sBAArB;gBAE0B,YAAY,EAAA,CAAA;sBAAtC,SAAS;uBAAC,cAAc;gBACM,gBAAgB,EAAA,CAAA;sBAA9C,SAAS;uBAAC,kBAAkB;;;ACzC/B;AA0CA;;AAEG;MAEU,mBAAmB,CAAA;AACV,IAAA,SAAA;AAApB,IAAA,WAAA,CAAoB,SAA0B,EAAA;QAA1B,IAAA,CAAA,SAAS,GAAT,SAAS;;AAE7B;;;;;;AAMG;AACH,IAAA,MAAM,WAAW,CAAC,SAAiB,EAAE,SAA6B,EAAE,EAAA;QAClE,MAAM,EACJ,UAAU,GAAG,QAAQ,EACrB,QAAQ,GAAG,MAAM,EACjB,WAAW,GAAG,EAAE,GAAG,CAAC,EACpB,OAAO,GAAG,GAAG,EACb,YAAY,GAAG,YAAY,EAC5B,GAAG,MAAM;QAEV,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;AACxC,YAAA,SAAS,EAAE,qBAAqB;AAChC,YAAA,cAAc,EAAE;AACd,gBAAA,QAAQ,EAAE,SAAS;gBACnB,WAAW;gBACX,UAAU;gBACV,QAAQ;gBACR,OAAO;gBACP,YAAY;gBACZ,SAAS,EAAE,IAAI,CAAC,SAAS;AAC1B,aAAA;AACD,YAAA,QAAQ,EAAE,mBAAmB;AAC9B,SAAA,CAAC;AAEF,QAAA,MAAM,KAAK,CAAC,OAAO,EAAE;QACrB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,KAAK,CAAC,aAAa,EAAE;AAE5C,QAAA,IAAI,CAAC,IAAI;AAAE,YAAA,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC;AAC5C,QAAA,OAAO,IAAI;;AAGb;;;;;AAKG;AACH,IAAA,MAAM,gBAAgB,CAAC,MAAA,GAA6B,EAAE,EAAA;AACpD,QAAA,IAAI;AACF,YAAA,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC;AAClC,gBAAA,OAAO,EAAE,EAAE;gBACX,UAAU,EAAE,gBAAgB,CAAC,GAAG;gBAChC,MAAM,EAAE,YAAY,CAAC,MAAM;AAC3B,gBAAA,YAAY,EAAE,KAAK;AACpB,aAAA,CAAC;;YAGF,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI;YAE7C,IAAI,CAAC,SAAS,EAAE;AACd,gBAAA,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC;;YAGtE,OAAO,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,MAAM,CAAC;;QAC1C,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC;AAClD,YAAA,MAAM,KAAK;;;uGAjEJ,mBAAmB,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,eAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;2GAAnB,mBAAmB,EAAA,CAAA;;2FAAnB,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAD/B;;;AC7CD;;AAEG;AAKH;AACO,MAAM,MAAM,GAAG;;ACRtB;;AAEG;;;;"}