import { UpploadEffect } from "../../effect"; import Cropper from "cropperjs"; import { IHandlersParams, ITemplateParams, IUpploadFile, } from "../../helpers/interfaces"; import { safeListen, fitImageToContainer, canvasToBlob, } from "../../helpers/elements"; type CropNum = 1 | 2 | 3 | undefined; export default class Crop extends UpploadEffect { name = "crop"; icon = ``; aspectRatio = NaN; hideAspectRatioSettings = false; aspectRatioOptions = { free: NaN, square: 1, "16:9": 16 / 9, } as { [index: string]: number }; autoCropArea: CropNum = 1; viewMode: CropNum = 1; originalFile: IUpploadFile = { blob: new Blob() }; constructor({ aspectRatio, aspectRatioOptions, hideAspectRatioSettings, autoCropArea, viewMode, }: { aspectRatio?: number; aspectRatioOptions?: { [index: string]: number }; hideAspectRatioSettings?: boolean; autoCropArea?: CropNum; viewMode?: CropNum; } = {}) { super(); if (aspectRatio) this.aspectRatio = aspectRatio; if (aspectRatioOptions) this.aspectRatioOptions = aspectRatioOptions; if (autoCropArea) this.autoCropArea = autoCropArea; if (viewMode) this.viewMode = viewMode; if (hideAspectRatioSettings) this.hideAspectRatioSettings = hideAspectRatioSettings; } template = ({ file, translate }: ITemplateParams) => { const image = URL.createObjectURL(file.blob); this.originalFile = file; return `
${ !this.aspectRatio && !this.hideAspectRatioSettings ? `
${Object.keys(this.aspectRatioOptions) .map( (aspectRatio, index) => ` ` ) .join("")}
` : "" } `; }; handlers = (params: IHandlersParams) => { const cropperElement = params.uppload.container.querySelector( ".uppload-cropping-element img" ) as HTMLImageElement | null; const originalFile = this.originalFile; const type = originalFile.type && ["image/jpeg", "image/webp"].indexOf(originalFile.type) !== -1 ? originalFile.type : "image/png"; if (cropperElement) { fitImageToContainer(params, cropperElement).then(() => { const cropper = new Cropper(cropperElement, { aspectRatio: this.aspectRatio, autoCropArea: this.autoCropArea, viewMode: this.viewMode, ready() { canvasToBlob(cropper.getCroppedCanvas(), type).then((blob) => { originalFile.blob = blob; params.next(originalFile); }); }, cropend() { canvasToBlob(cropper.getCroppedCanvas(), type).then((blob) => { originalFile.blob = blob; params.next(originalFile); }); }, }); const aspectRatios = params.uppload.container.querySelectorAll( "input[name='crop-aspect-ratio']" ); aspectRatios.forEach((aspectRatio) => { safeListen(aspectRatio, "change", () => { const selectedAspectRatio = params.uppload.container.querySelector( "input[name='crop-aspect-ratio']:checked" ); if (selectedAspectRatio) { cropper.setAspectRatio( this.aspectRatioOptions[ selectedAspectRatio.getAttribute("data-name") || "free" ] ); canvasToBlob(cropper.getCroppedCanvas(), type).then((blob) => { originalFile.blob = blob; params.next(originalFile); }); } }); }); }); } }; }