From b140a08497acde836cb69970746b0c5c2de311a3 Mon Sep 17 00:00:00 2001 From: Cyperghost Date: Thu, 5 Dec 2024 11:37:49 +0100 Subject: [PATCH] Set the default selection to the maximum width --- .../Core/Component/Image/Cropper.ts | 72 +++++++++++++------ .../Core/Component/Image/Cropper.js | 56 +++++++++------ 2 files changed, 84 insertions(+), 44 deletions(-) diff --git a/ts/WoltLabSuite/Core/Component/Image/Cropper.ts b/ts/WoltLabSuite/Core/Component/Image/Cropper.ts index f85cf2dc8f..7ac8922f28 100644 --- a/ts/WoltLabSuite/Core/Component/Image/Cropper.ts +++ b/ts/WoltLabSuite/Core/Component/Image/Cropper.ts @@ -25,6 +25,15 @@ export interface CropperConfiguration { }[]; } +function inSelection(selection: Selection, maxSelection: Selection): boolean { + return ( + selection.x >= maxSelection.x && + selection.y >= maxSelection.y && + selection.x + selection.width <= maxSelection.x + maxSelection.width && + selection.y + selection.height <= maxSelection.y + maxSelection.height + ); +} + abstract class ImageCropper { readonly configuration: CropperConfiguration; readonly file: File; @@ -128,7 +137,7 @@ abstract class ImageCropper { protected setCropperStyle() { this.cropperCanvas!.style.aspectRatio = `${this.width}/${this.height}`; - if (this.width > this.height) { + if (this.width >= this.height) { this.cropperCanvas!.style.width = `min(70vw, ${this.width}px)`; this.cropperCanvas!.style.height = "auto"; } else { @@ -153,9 +162,8 @@ abstract class ImageCropper { if (this.orientation) { this.cropperImage!.$rotate(`${this.orientation}deg`); } - this.cropperImage!.$center("contain"); - this.cropperSelection!.$center(); - this.cropperSelection!.scrollIntoView({ block: "center", inline: "center" }); + + this.centerSelection(); // Limit the selection to the canvas boundaries this.cropperSelection!.addEventListener("change", (event: CustomEvent) => { @@ -163,23 +171,25 @@ abstract class ImageCropper { const cropperCanvasRect = this.cropperCanvas!.getBoundingClientRect(); const selection = event.detail as Selection; + const cropperImageRect = this.cropperImage!.getBoundingClientRect(); const maxSelection: Selection = { - x: 0, - y: 0, - width: cropperCanvasRect.width, - height: cropperCanvasRect.height, + x: cropperImageRect.left - cropperCanvasRect.left, + y: cropperImageRect.top - cropperCanvasRect.top, + width: cropperImageRect.width, + height: cropperImageRect.height, }; - if ( - selection.x < maxSelection.x || - selection.y < maxSelection.y || - selection.x + selection.width > maxSelection.x + maxSelection.width || - selection.y + selection.height > maxSelection.y + maxSelection.height - ) { + if (!inSelection(selection, maxSelection)) { event.preventDefault(); } }); } + + protected centerSelection(): void { + this.cropperImage!.$center("contain"); + this.cropperSelection!.$center(); + this.cropperSelection!.scrollIntoView({ block: "center", inline: "center" }); + } } class ExactImageCropper extends ImageCropper { @@ -284,10 +294,10 @@ class MinMaxImageCropper extends ImageCropper { protected getCropperTemplate(): string { return `
- + - + @@ -308,19 +318,18 @@ class MinMaxImageCropper extends ImageCropper { protected setCropperStyle() { super.setCropperStyle(); - this.cropperSelection!.width = Math.min(this.width, this.maxSize.width); - this.cropperSelection!.height = Math.min(this.height, this.maxSize.height); - this.cropperCanvas!.style.minWidth = `min(${this.maxSize.width}px, ${this.width}px)`; - this.cropperCanvas!.style.minHeight = `min(${this.maxSize.height}px, ${this.height}px)`; + if (this.width >= this.height) { + this.cropperCanvas!.style.width = `${Math.min(this.maxSize.width, this.width)}px`; + } else { + this.cropperCanvas!.style.height = `${Math.min(this.maxSize.height, this.height)}px`; + } } protected createCropper() { super.createCropper(); this.dialog!.addEventListener("extra", () => { - this.cropperImage!.$center("contain"); - this.cropperSelection!.$reset(); - this.cropperSelection!.scrollIntoView({ block: "center", inline: "center" }); + this.centerSelection(); }); // Limit the selection to the min/max size @@ -337,6 +346,23 @@ class MinMaxImageCropper extends ImageCropper { } }); } + + protected centerSelection(): void { + this.cropperImage!.$center("contain"); + + const { width: imageWidth } = this.cropperImage!.getBoundingClientRect(); + + this.cropperSelection!.$change( + 0, + 0, + imageWidth, + 0, + this.configuration.aspectRatio, + true, + ); + this.cropperSelection!.$center(); + this.cropperSelection!.scrollIntoView({ block: "center", inline: "center" }); + } } export async function cropImage( diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Component/Image/Cropper.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Component/Image/Cropper.js index 8441b7e135..86794834c6 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Component/Image/Cropper.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Component/Image/Cropper.js @@ -13,6 +13,12 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Image/Resizer", "WoltL Resizer_1 = tslib_1.__importDefault(Resizer_1); cropperjs_1 = tslib_1.__importDefault(cropperjs_1); exifreader_1 = tslib_1.__importDefault(exifreader_1); + function inSelection(selection, maxSelection) { + return (selection.x >= maxSelection.x && + selection.y >= maxSelection.y && + selection.x + selection.width <= maxSelection.x + maxSelection.width && + selection.y + selection.height <= maxSelection.y + maxSelection.height); + } class ImageCropper { configuration; file; @@ -100,7 +106,7 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Image/Resizer", "WoltL } setCropperStyle() { this.cropperCanvas.style.aspectRatio = `${this.width}/${this.height}`; - if (this.width > this.height) { + if (this.width >= this.height) { this.cropperCanvas.style.width = `min(70vw, ${this.width}px)`; this.cropperCanvas.style.height = "auto"; } @@ -121,28 +127,29 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Image/Resizer", "WoltL if (this.orientation) { this.cropperImage.$rotate(`${this.orientation}deg`); } - this.cropperImage.$center("contain"); - this.cropperSelection.$center(); - this.cropperSelection.scrollIntoView({ block: "center", inline: "center" }); + this.centerSelection(); // Limit the selection to the canvas boundaries this.cropperSelection.addEventListener("change", (event) => { // see https://fengyuanchen.github.io/cropperjs/v2/api/cropper-selection.html#limit-boundaries const cropperCanvasRect = this.cropperCanvas.getBoundingClientRect(); const selection = event.detail; + const cropperImageRect = this.cropperImage.getBoundingClientRect(); const maxSelection = { - x: 0, - y: 0, - width: cropperCanvasRect.width, - height: cropperCanvasRect.height, + x: cropperImageRect.left - cropperCanvasRect.left, + y: cropperImageRect.top - cropperCanvasRect.top, + width: cropperImageRect.width, + height: cropperImageRect.height, }; - if (selection.x < maxSelection.x || - selection.y < maxSelection.y || - selection.x + selection.width > maxSelection.x + maxSelection.width || - selection.y + selection.height > maxSelection.y + maxSelection.height) { + if (!inSelection(selection, maxSelection)) { event.preventDefault(); } }); } + centerSelection() { + this.cropperImage.$center("contain"); + this.cropperSelection.$center(); + this.cropperSelection.scrollIntoView({ block: "center", inline: "center" }); + } } class ExactImageCropper extends ImageCropper { #size; @@ -214,10 +221,10 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Image/Resizer", "WoltL } getCropperTemplate() { return `
- + - + @@ -236,17 +243,17 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Image/Resizer", "WoltL } setCropperStyle() { super.setCropperStyle(); - this.cropperSelection.width = Math.min(this.width, this.maxSize.width); - this.cropperSelection.height = Math.min(this.height, this.maxSize.height); - this.cropperCanvas.style.minWidth = `min(${this.maxSize.width}px, ${this.width}px)`; - this.cropperCanvas.style.minHeight = `min(${this.maxSize.height}px, ${this.height}px)`; + if (this.width >= this.height) { + this.cropperCanvas.style.width = `${Math.min(this.maxSize.width, this.width)}px`; + } + else { + this.cropperCanvas.style.height = `${Math.min(this.maxSize.height, this.height)}px`; + } } createCropper() { super.createCropper(); this.dialog.addEventListener("extra", () => { - this.cropperImage.$center("contain"); - this.cropperSelection.$reset(); - this.cropperSelection.scrollIntoView({ block: "center", inline: "center" }); + this.centerSelection(); }); // Limit the selection to the min/max size this.cropperSelection.addEventListener("change", (event) => { @@ -259,6 +266,13 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Image/Resizer", "WoltL } }); } + centerSelection() { + this.cropperImage.$center("contain"); + const { width: imageWidth } = this.cropperImage.getBoundingClientRect(); + this.cropperSelection.$change(0, 0, imageWidth, 0, this.configuration.aspectRatio, true); + this.cropperSelection.$center(); + this.cropperSelection.scrollIntoView({ block: "center", inline: "center" }); + } } async function cropImage(element, file, configuration) { switch (file.type) { -- 2.20.1