protected dialog?: WoltlabCoreDialogElement;
protected exif?: ExifUtil.Exif;
protected orientation?: number;
+ protected cropperCanvasRect?: DOMRect;
#cropper?: Cropper;
constructor(element: WoltlabCoreFileUploadElement, file: File, configuration: CropperConfiguration) {
}
}
+ abstract get minSize(): { width: number; height: number };
+
+ abstract get maxSize(): { width: number; height: number };
+
+ public async loadImage() {
+ const { image, exif } = await this.resizer.loadFile(this.file);
+ this.image = image;
+ this.exif = exif;
+ const tags = await ExifReader.load(this.file);
+ if (tags.Orientation) {
+ switch (tags.Orientation.value) {
+ case 3:
+ this.orientation = 180;
+ break;
+ case 6:
+ this.orientation = 90;
+ break;
+ case 8:
+ this.orientation = 270;
+ break;
+ // Any other rotation is unsupported.
+ }
+ }
+ }
+
public async showDialog(): Promise<File> {
this.dialog = dialogFactory().fromElement(this.image!).asPrompt({
extra: this.getDialogExtra(),
};
window.addEventListener("resize", resize, { passive: true });
- this.dialog.addEventListener(
- "afterClose",
- () => {
- window.removeEventListener("resize", resize);
- },
- {
- once: true,
- },
- );
return new Promise<File>((resolve, reject) => {
+ let callReject = true;
+ this.dialog!.addEventListener("afterClose", () => {
+ window.removeEventListener("resize", resize);
+
+ // If the dialog is closed without confirming, reject the promise to trigger a cancel event.
+ if (callReject) {
+ reject();
+ }
+ });
+
this.dialog!.addEventListener("primary", () => {
+ callReject = false;
+
void this.getCanvas()
.then((canvas) => {
this.resizer
});
}
- protected getCanvas(): Promise<HTMLCanvasElement> {
- return this.cropperSelection!.$toCanvas();
- }
-
- public async loadImage() {
- const { image, exif } = await this.resizer.loadFile(this.file);
- this.image = image;
- this.exif = exif;
- const tags = await ExifReader.load(this.file);
- if (tags.Orientation) {
- switch (tags.Orientation.value) {
- case 3:
- this.orientation = 180;
- break;
- case 6:
- this.orientation = 90;
- break;
- case 8:
- this.orientation = 270;
- break;
- // Any other rotation is unsupported.
- }
- }
- }
-
- protected abstract getCropperTemplate(): string;
-
protected getDialogExtra(): string | undefined {
return undefined;
}
- protected setCropperStyle() {
- this.cropperCanvas!.style.aspectRatio = `${this.width}/${this.height}`;
-
- if (this.width >= this.height) {
- this.cropperCanvas!.style.maxHeight = "100%";
- } else {
- this.cropperCanvas!.style.maxWidth = "100%";
- }
+ protected getCanvas(): Promise<HTMLCanvasElement> {
+ // Calculate the size of the image in relation to the window size
+ const selectionRatio = Math.min(
+ this.cropperCanvasRect!.width / this.width,
+ this.cropperCanvasRect!.height / this.height,
+ );
+ const width = this.cropperSelection!.width / selectionRatio;
+ const height = width / this.configuration.aspectRatio;
- this.cropperSelection!.aspectRatio = this.configuration.aspectRatio;
+ return this.cropperSelection!.$toCanvas({
+ width: Math.max(Math.min(Math.floor(width), this.maxSize.width), this.minSize.width),
+ height: Math.max(Math.min(Math.ceil(height), this.maxSize.height), this.minSize.height),
+ });
}
protected createCropper() {
event.preventDefault();
}
});
+
+ // Limit the selection to the min/max size
+ this.cropperSelection!.addEventListener("change", (event: CustomEvent) => {
+ const selection = event.detail as Selection;
+ this.cropperCanvasRect = this.cropperCanvas!.getBoundingClientRect();
+
+ const selectionRatio = Math.min(
+ this.cropperCanvasRect.width / this.width,
+ this.cropperCanvasRect.height / this.height,
+ );
+
+ const minWidth = this.minSize.width * selectionRatio;
+ const maxWidth = this.cropperCanvasRect.width;
+ const minHeight = minWidth / this.configuration.aspectRatio;
+ const maxHeight = maxWidth / this.configuration.aspectRatio;
+
+ if (
+ Math.round(selection.width) < minWidth ||
+ Math.round(selection.height) < minHeight ||
+ Math.round(selection.width) > maxWidth ||
+ Math.round(selection.height) > maxHeight
+ ) {
+ event.preventDefault();
+ }
+ });
+ }
+
+ protected setCropperStyle() {
+ this.cropperCanvas!.style.aspectRatio = `${this.width}/${this.height}`;
+
+ this.cropperSelection!.aspectRatio = this.configuration.aspectRatio;
}
protected centerSelection(): void {
+ // Set to the maximum size
+ this.cropperCanvas!.style.width = `${this.width}px`;
+ this.cropperCanvas!.style.height = `${this.height}px`;
+
+ const dimension = DomUtil.innerDimensions(this.cropperCanvas!.parentElement!);
+ const ratio = Math.min(dimension.width / this.width, dimension.height / this.height);
+
+ this.cropperCanvas!.style.height = `${this.height * ratio}px`;
+ this.cropperCanvas!.style.width = `${this.width * ratio}px`;
+
this.cropperImage!.$center("contain");
+ this.cropperCanvasRect = this.cropperImage!.getBoundingClientRect();
+
+ const selectionRatio = Math.min(
+ this.cropperCanvasRect.width / this.maxSize.width,
+ this.cropperCanvasRect.height / this.maxSize.height,
+ );
+
+ this.cropperSelection!.$change(
+ 0,
+ 0,
+ this.maxSize.width * selectionRatio,
+ this.maxSize.height * selectionRatio,
+ this.configuration.aspectRatio,
+ true,
+ );
+
this.cropperSelection!.$center();
this.cropperSelection!.scrollIntoView({ block: "center", inline: "center" });
}
+
+ protected getCropperTemplate(): string {
+ return `<cropper-canvas background scale-step="0.0">
+ <cropper-image skewable scalable translatable rotatable></cropper-image>
+ <cropper-shade hidden></cropper-shade>
+ <cropper-handle action="scale" hidden disabled></cropper-handle>
+ <cropper-selection precise movable resizable outlined>
+ <cropper-grid role="grid" bordered covered></cropper-grid>
+ <cropper-crosshair centered></cropper-crosshair>
+ <cropper-handle action="move" theme-color="rgba(255, 255, 255, 0.35)"></cropper-handle>
+ <cropper-handle action="n-resize"></cropper-handle>
+ <cropper-handle action="e-resize"></cropper-handle>
+ <cropper-handle action="s-resize"></cropper-handle>
+ <cropper-handle action="w-resize"></cropper-handle>
+ <cropper-handle action="ne-resize"></cropper-handle>
+ <cropper-handle action="nw-resize"></cropper-handle>
+ <cropper-handle action="se-resize"></cropper-handle>
+ <cropper-handle action="sw-resize"></cropper-handle>
+ </cropper-selection>
+</cropper-canvas>`;
+ }
}
class ExactImageCropper extends ImageCropper {
- #size?: { width: number; height: number };
+ get minSize() {
+ return this.configuration.sizes[0];
+ }
+
+ get maxSize() {
+ return this.configuration.sizes[this.configuration.sizes.length - 1];
+ }
public async showDialog(): Promise<File> {
// The image already has the correct size, cropping is not necessary
if (
- this.width == this.#size!.width &&
- this.height == this.#size!.height &&
+ this.configuration.sizes.filter((size) => {
+ return size.width == this.width && size.height == this.height;
+ }).length > 0 &&
this.image instanceof HTMLCanvasElement
) {
return this.resizer.saveFile(
public async loadImage(): Promise<void> {
await super.loadImage();
- const timeout = new Promise<File>((resolve) => {
- window.setTimeout(() => resolve(this.file), 10_000);
- });
-
- // resize image to the largest possible size
- const sizes = this.configuration.sizes.filter((size) => {
- return size.width <= this.width && size.height <= this.height;
- });
+ const sizes = this.configuration.sizes
+ .filter((size) => {
+ return size.width <= this.width && size.height <= this.height;
+ })
+ .sort((a, b) => {
+ if (this.configuration.aspectRatio >= 1) {
+ return a.width - b.width;
+ } else {
+ return a.height - b.height;
+ }
+ });
if (sizes.length === 0) {
const smallestSize =
);
}
- this.#size = sizes[sizes.length - 1];
- this.image = await this.resizer.resize(
- this.image as HTMLImageElement,
- this.width >= this.height ? this.width : this.#size.width,
- this.height > this.width ? this.height : this.#size.height,
- this.resizer.quality,
- true,
- timeout,
- );
- }
-
- protected getCropperTemplate(): string {
- return `<cropper-canvas background>
- <cropper-image rotatable></cropper-image>
- <cropper-shade hidden></cropper-shade>
- <cropper-selection movable outlined keyboard>
- <cropper-grid role="grid" bordered covered></cropper-grid>
- <cropper-crosshair centered></cropper-crosshair>
- <cropper-handle action="move" theme-color="rgba(255, 255, 255, 0.35)"></cropper-handle>
- </cropper-selection>
-</cropper-canvas>`;
- }
-
- protected setCropperStyle() {
- super.setCropperStyle();
-
- this.cropperSelection!.width = this.#size!.width;
- this.cropperSelection!.height = this.#size!.height;
-
- this.cropperCanvas!.style.width = `${this.width}px`;
- this.cropperCanvas!.style.height = `${this.height}px`;
- this.cropperSelection!.style.removeProperty("aspectRatio");
+ this.configuration.sizes = sizes;
}
}
class MinMaxImageCropper extends ImageCropper {
- #cropperCanvasRect?: DOMRect;
constructor(element: WoltlabCoreFileUploadElement, file: File, configuration: CropperConfiguration) {
super(element, file, configuration);
if (configuration.sizes.length !== 2) {
public async loadImage(): Promise<void> {
await super.loadImage();
- if (this.image!.width < this.minSize.width || this.image!.height < this.minSize.height) {
+ if (this.width < this.minSize.width || this.height < this.minSize.height) {
throw new Error(
getPhrase("wcf.upload.error.image.tooSmall", {
width: this.minSize.width,
}
}
- protected getCropperTemplate(): string {
- return `<cropper-canvas background scale-step="0.0">
- <cropper-image skewable scalable translatable rotatable></cropper-image>
- <cropper-shade hidden></cropper-shade>
- <cropper-handle action="scale" hidden disabled></cropper-handle>
- <cropper-selection precise movable resizable outlined>
- <cropper-grid role="grid" bordered covered></cropper-grid>
- <cropper-crosshair centered></cropper-crosshair>
- <cropper-handle action="move" theme-color="rgba(255, 255, 255, 0.35)"></cropper-handle>
- <cropper-handle action="n-resize"></cropper-handle>
- <cropper-handle action="e-resize"></cropper-handle>
- <cropper-handle action="s-resize"></cropper-handle>
- <cropper-handle action="w-resize"></cropper-handle>
- <cropper-handle action="ne-resize"></cropper-handle>
- <cropper-handle action="nw-resize"></cropper-handle>
- <cropper-handle action="se-resize"></cropper-handle>
- <cropper-handle action="sw-resize"></cropper-handle>
- </cropper-selection>
-</cropper-canvas>`;
- }
-
protected createCropper() {
super.createCropper();
this.dialog!.addEventListener("extra", () => {
this.centerSelection();
});
-
- // Limit the selection to the min/max size
- this.cropperSelection!.addEventListener("change", (event: CustomEvent) => {
- const selection = event.detail as Selection;
- this.#cropperCanvasRect = this.cropperCanvas!.getBoundingClientRect();
-
- const maxImageWidth = Math.min(this.image!.width, this.maxSize.width);
- const maxImageHeight = Math.min(this.image!.height, this.maxSize.height);
- const selectionRatio = Math.min(
- this.#cropperCanvasRect.width / maxImageWidth,
- this.#cropperCanvasRect.height / maxImageHeight,
- );
-
- const minWidth = this.minSize.width * selectionRatio;
- const maxWidth = this.maxSize.width * selectionRatio;
- const minHeight = minWidth / this.configuration.aspectRatio;
- const maxHeight = maxWidth / this.configuration.aspectRatio;
-
- if (
- Math.round(selection.width) < minWidth ||
- Math.round(selection.height) < minHeight ||
- Math.round(selection.width) > maxWidth ||
- Math.round(selection.height) > maxHeight
- ) {
- event.preventDefault();
- }
- });
- }
-
- protected getCanvas(): Promise<HTMLCanvasElement> {
- // Calculate the size of the image in relation to the window size
- const maxImageWidth = Math.min(this.image!.width, this.maxSize.width);
- const widthRatio = this.#cropperCanvasRect!.width / maxImageWidth;
- const width = this.cropperSelection!.width / widthRatio;
- const height = width / this.configuration.aspectRatio;
-
- return this.cropperSelection!.$toCanvas({
- width: Math.max(Math.min(Math.ceil(width), this.maxSize.width), this.minSize.width),
- height: Math.max(Math.min(Math.ceil(height), this.maxSize.height), this.minSize.height),
- });
- }
-
- protected centerSelection(): void {
- // Reset to get the maximum available height and width
- this.cropperCanvas!.style.height = "";
- this.cropperCanvas!.style.width = "";
-
- const dimension = DomUtil.innerDimensions(this.cropperCanvas!.parentElement!);
- const ratio = Math.min(dimension.width / this.image!.width, dimension.height / this.image!.height);
-
- this.cropperCanvas!.style.height = `${this.image!.height * ratio}px`;
- this.cropperCanvas!.style.width = `${this.image!.width * ratio}px`;
-
- this.cropperImage!.$center("contain");
- this.#cropperCanvasRect = this.cropperImage!.getBoundingClientRect();
-
- const selectionRatio = Math.min(
- this.#cropperCanvasRect.width / this.maxSize.width,
- this.#cropperCanvasRect.height / this.maxSize.height,
- );
-
- this.cropperSelection!.$change(
- 0,
- 0,
- this.maxSize.width * selectionRatio,
- this.maxSize.height * selectionRatio,
- this.configuration.aspectRatio,
- true,
- );
-
- this.cropperSelection!.$center();
- this.cropperSelection!.scrollIntoView({ block: "center", inline: "center" });
}
}
dialog;
exif;
orientation;
+ cropperCanvasRect;
#cropper;
constructor(element, file, configuration) {
this.configuration = configuration;
return this.image.height;
}
}
+ async loadImage() {
+ const { image, exif } = await this.resizer.loadFile(this.file);
+ this.image = image;
+ this.exif = exif;
+ const tags = await exifreader_1.default.load(this.file);
+ if (tags.Orientation) {
+ switch (tags.Orientation.value) {
+ case 3:
+ this.orientation = 180;
+ break;
+ case 6:
+ this.orientation = 90;
+ break;
+ case 8:
+ this.orientation = 270;
+ break;
+ // Any other rotation is unsupported.
+ }
+ }
+ }
async showDialog() {
this.dialog = (0, Dialog_1.dialogFactory)().fromElement(this.image).asPrompt({
extra: this.getDialogExtra(),
this.centerSelection();
};
window.addEventListener("resize", resize, { passive: true });
- this.dialog.addEventListener("afterClose", () => {
- window.removeEventListener("resize", resize);
- }, {
- once: true,
- });
return new Promise((resolve, reject) => {
+ let callReject = true;
+ this.dialog.addEventListener("afterClose", () => {
+ window.removeEventListener("resize", resize);
+ // If the dialog is closed without confirming, reject the promise to trigger a cancel event.
+ if (callReject) {
+ reject();
+ }
+ });
this.dialog.addEventListener("primary", () => {
+ callReject = false;
void this.getCanvas()
.then((canvas) => {
this.resizer
});
});
}
- getCanvas() {
- return this.cropperSelection.$toCanvas();
- }
- async loadImage() {
- const { image, exif } = await this.resizer.loadFile(this.file);
- this.image = image;
- this.exif = exif;
- const tags = await exifreader_1.default.load(this.file);
- if (tags.Orientation) {
- switch (tags.Orientation.value) {
- case 3:
- this.orientation = 180;
- break;
- case 6:
- this.orientation = 90;
- break;
- case 8:
- this.orientation = 270;
- break;
- // Any other rotation is unsupported.
- }
- }
- }
getDialogExtra() {
return undefined;
}
- setCropperStyle() {
- this.cropperCanvas.style.aspectRatio = `${this.width}/${this.height}`;
- if (this.width >= this.height) {
- this.cropperCanvas.style.maxHeight = "100%";
- }
- else {
- this.cropperCanvas.style.maxWidth = "100%";
- }
- this.cropperSelection.aspectRatio = this.configuration.aspectRatio;
+ getCanvas() {
+ // Calculate the size of the image in relation to the window size
+ const selectionRatio = Math.min(this.cropperCanvasRect.width / this.width, this.cropperCanvasRect.height / this.height);
+ const width = this.cropperSelection.width / selectionRatio;
+ const height = width / this.configuration.aspectRatio;
+ return this.cropperSelection.$toCanvas({
+ width: Math.max(Math.min(Math.floor(width), this.maxSize.width), this.minSize.width),
+ height: Math.max(Math.min(Math.ceil(height), this.maxSize.height), this.minSize.height),
+ });
}
createCropper() {
this.#cropper = new cropperjs_1.default(this.image, {
event.preventDefault();
}
});
+ // Limit the selection to the min/max size
+ this.cropperSelection.addEventListener("change", (event) => {
+ const selection = event.detail;
+ this.cropperCanvasRect = this.cropperCanvas.getBoundingClientRect();
+ const selectionRatio = Math.min(this.cropperCanvasRect.width / this.width, this.cropperCanvasRect.height / this.height);
+ const minWidth = this.minSize.width * selectionRatio;
+ const maxWidth = this.cropperCanvasRect.width;
+ const minHeight = minWidth / this.configuration.aspectRatio;
+ const maxHeight = maxWidth / this.configuration.aspectRatio;
+ if (Math.round(selection.width) < minWidth ||
+ Math.round(selection.height) < minHeight ||
+ Math.round(selection.width) > maxWidth ||
+ Math.round(selection.height) > maxHeight) {
+ event.preventDefault();
+ }
+ });
+ }
+ setCropperStyle() {
+ this.cropperCanvas.style.aspectRatio = `${this.width}/${this.height}`;
+ this.cropperSelection.aspectRatio = this.configuration.aspectRatio;
}
centerSelection() {
+ // Set to the maximum size
+ this.cropperCanvas.style.width = `${this.width}px`;
+ this.cropperCanvas.style.height = `${this.height}px`;
+ const dimension = Util_1.default.innerDimensions(this.cropperCanvas.parentElement);
+ const ratio = Math.min(dimension.width / this.width, dimension.height / this.height);
+ this.cropperCanvas.style.height = `${this.height * ratio}px`;
+ this.cropperCanvas.style.width = `${this.width * ratio}px`;
this.cropperImage.$center("contain");
+ this.cropperCanvasRect = this.cropperImage.getBoundingClientRect();
+ const selectionRatio = Math.min(this.cropperCanvasRect.width / this.maxSize.width, this.cropperCanvasRect.height / this.maxSize.height);
+ this.cropperSelection.$change(0, 0, this.maxSize.width * selectionRatio, this.maxSize.height * selectionRatio, this.configuration.aspectRatio, true);
this.cropperSelection.$center();
this.cropperSelection.scrollIntoView({ block: "center", inline: "center" });
}
+ getCropperTemplate() {
+ return `<cropper-canvas background scale-step="0.0">
+ <cropper-image skewable scalable translatable rotatable></cropper-image>
+ <cropper-shade hidden></cropper-shade>
+ <cropper-handle action="scale" hidden disabled></cropper-handle>
+ <cropper-selection precise movable resizable outlined>
+ <cropper-grid role="grid" bordered covered></cropper-grid>
+ <cropper-crosshair centered></cropper-crosshair>
+ <cropper-handle action="move" theme-color="rgba(255, 255, 255, 0.35)"></cropper-handle>
+ <cropper-handle action="n-resize"></cropper-handle>
+ <cropper-handle action="e-resize"></cropper-handle>
+ <cropper-handle action="s-resize"></cropper-handle>
+ <cropper-handle action="w-resize"></cropper-handle>
+ <cropper-handle action="ne-resize"></cropper-handle>
+ <cropper-handle action="nw-resize"></cropper-handle>
+ <cropper-handle action="se-resize"></cropper-handle>
+ <cropper-handle action="sw-resize"></cropper-handle>
+ </cropper-selection>
+</cropper-canvas>`;
+ }
}
class ExactImageCropper extends ImageCropper {
- #size;
+ get minSize() {
+ return this.configuration.sizes[0];
+ }
+ get maxSize() {
+ return this.configuration.sizes[this.configuration.sizes.length - 1];
+ }
async showDialog() {
// The image already has the correct size, cropping is not necessary
- if (this.width == this.#size.width &&
- this.height == this.#size.height &&
+ if (this.configuration.sizes.filter((size) => {
+ return size.width == this.width && size.height == this.height;
+ }).length > 0 &&
this.image instanceof HTMLCanvasElement) {
return this.resizer.saveFile({ exif: this.orientation ? undefined : this.exif, image: this.image }, this.file.name, this.file.type);
}
}
async loadImage() {
await super.loadImage();
- const timeout = new Promise((resolve) => {
- window.setTimeout(() => resolve(this.file), 10_000);
- });
- // resize image to the largest possible size
- const sizes = this.configuration.sizes.filter((size) => {
+ const sizes = this.configuration.sizes
+ .filter((size) => {
return size.width <= this.width && size.height <= this.height;
+ })
+ .sort((a, b) => {
+ if (this.configuration.aspectRatio >= 1) {
+ return a.width - b.width;
+ }
+ else {
+ return a.height - b.height;
+ }
});
if (sizes.length === 0) {
const smallestSize = this.configuration.sizes.length > 1 ? this.configuration.sizes[this.configuration.sizes.length - 1] : undefined;
height: smallestSize?.height,
}));
}
- this.#size = sizes[sizes.length - 1];
- this.image = await this.resizer.resize(this.image, this.width >= this.height ? this.width : this.#size.width, this.height > this.width ? this.height : this.#size.height, this.resizer.quality, true, timeout);
- }
- getCropperTemplate() {
- return `<cropper-canvas background>
- <cropper-image rotatable></cropper-image>
- <cropper-shade hidden></cropper-shade>
- <cropper-selection movable outlined keyboard>
- <cropper-grid role="grid" bordered covered></cropper-grid>
- <cropper-crosshair centered></cropper-crosshair>
- <cropper-handle action="move" theme-color="rgba(255, 255, 255, 0.35)"></cropper-handle>
- </cropper-selection>
-</cropper-canvas>`;
- }
- setCropperStyle() {
- super.setCropperStyle();
- this.cropperSelection.width = this.#size.width;
- this.cropperSelection.height = this.#size.height;
- this.cropperCanvas.style.width = `${this.width}px`;
- this.cropperCanvas.style.height = `${this.height}px`;
- this.cropperSelection.style.removeProperty("aspectRatio");
+ this.configuration.sizes = sizes;
}
}
class MinMaxImageCropper extends ImageCropper {
- #cropperCanvasRect;
constructor(element, file, configuration) {
super(element, file, configuration);
if (configuration.sizes.length !== 2) {
}
async loadImage() {
await super.loadImage();
- if (this.image.width < this.minSize.width || this.image.height < this.minSize.height) {
+ if (this.width < this.minSize.width || this.height < this.minSize.height) {
throw new Error((0, Language_1.getPhrase)("wcf.upload.error.image.tooSmall", {
width: this.minSize.width,
height: this.minSize.height,
}));
}
}
- getCropperTemplate() {
- return `<cropper-canvas background scale-step="0.0">
- <cropper-image skewable scalable translatable rotatable></cropper-image>
- <cropper-shade hidden></cropper-shade>
- <cropper-handle action="scale" hidden disabled></cropper-handle>
- <cropper-selection precise movable resizable outlined>
- <cropper-grid role="grid" bordered covered></cropper-grid>
- <cropper-crosshair centered></cropper-crosshair>
- <cropper-handle action="move" theme-color="rgba(255, 255, 255, 0.35)"></cropper-handle>
- <cropper-handle action="n-resize"></cropper-handle>
- <cropper-handle action="e-resize"></cropper-handle>
- <cropper-handle action="s-resize"></cropper-handle>
- <cropper-handle action="w-resize"></cropper-handle>
- <cropper-handle action="ne-resize"></cropper-handle>
- <cropper-handle action="nw-resize"></cropper-handle>
- <cropper-handle action="se-resize"></cropper-handle>
- <cropper-handle action="sw-resize"></cropper-handle>
- </cropper-selection>
-</cropper-canvas>`;
- }
createCropper() {
super.createCropper();
this.dialog.addEventListener("extra", () => {
this.centerSelection();
});
- // Limit the selection to the min/max size
- this.cropperSelection.addEventListener("change", (event) => {
- const selection = event.detail;
- this.#cropperCanvasRect = this.cropperCanvas.getBoundingClientRect();
- const maxImageWidth = Math.min(this.image.width, this.maxSize.width);
- const maxImageHeight = Math.min(this.image.height, this.maxSize.height);
- const selectionRatio = Math.min(this.#cropperCanvasRect.width / maxImageWidth, this.#cropperCanvasRect.height / maxImageHeight);
- const minWidth = this.minSize.width * selectionRatio;
- const maxWidth = this.maxSize.width * selectionRatio;
- const minHeight = minWidth / this.configuration.aspectRatio;
- const maxHeight = maxWidth / this.configuration.aspectRatio;
- if (Math.round(selection.width) < minWidth ||
- Math.round(selection.height) < minHeight ||
- Math.round(selection.width) > maxWidth ||
- Math.round(selection.height) > maxHeight) {
- event.preventDefault();
- }
- });
- }
- getCanvas() {
- // Calculate the size of the image in relation to the window size
- const maxImageWidth = Math.min(this.image.width, this.maxSize.width);
- const widthRatio = this.#cropperCanvasRect.width / maxImageWidth;
- const width = this.cropperSelection.width / widthRatio;
- const height = width / this.configuration.aspectRatio;
- return this.cropperSelection.$toCanvas({
- width: Math.max(Math.min(Math.ceil(width), this.maxSize.width), this.minSize.width),
- height: Math.max(Math.min(Math.ceil(height), this.maxSize.height), this.minSize.height),
- });
- }
- centerSelection() {
- // Reset to get the maximum available height and width
- this.cropperCanvas.style.height = "";
- this.cropperCanvas.style.width = "";
- const dimension = Util_1.default.innerDimensions(this.cropperCanvas.parentElement);
- const ratio = Math.min(dimension.width / this.image.width, dimension.height / this.image.height);
- this.cropperCanvas.style.height = `${this.image.height * ratio}px`;
- this.cropperCanvas.style.width = `${this.image.width * ratio}px`;
- this.cropperImage.$center("contain");
- this.#cropperCanvasRect = this.cropperImage.getBoundingClientRect();
- const selectionRatio = Math.min(this.#cropperCanvasRect.width / this.maxSize.width, this.#cropperCanvasRect.height / this.maxSize.height);
- this.cropperSelection.$change(0, 0, this.maxSize.width * selectionRatio, this.maxSize.height * selectionRatio, this.configuration.aspectRatio, true);
- this.cropperSelection.$center();
- this.cropperSelection.scrollIntoView({ block: "center", inline: "center" });
}
}
async function cropImage(element, file, configuration) {