Also note the maximum width that is available file-upload-image-crop
authorCyperghost <olaf_schmitz_1@t-online.de>
Tue, 10 Dec 2024 08:55:23 +0000 (09:55 +0100)
committerCyperghost <olaf_schmitz_1@t-online.de>
Tue, 10 Dec 2024 08:55:23 +0000 (09:55 +0100)
ts/WoltLabSuite/Core/Component/Image/Cropper.ts
wcfsetup/install/files/js/WoltLabSuite/Core/Component/Image/Cropper.js

index 9f3a22de7ae372741dd0b32f8ff1b13d952b82c0..9d9b942ce3efe861f40fcfeab1076a5a22d6b389 100644 (file)
@@ -28,10 +28,10 @@ export interface CropperConfiguration {
 
 function inSelection(selection: Selection, maxSelection: Selection): boolean {
   return (
-    Math.ceil(selection.x) >= maxSelection.x &&
-    Math.ceil(selection.y) >= maxSelection.y &&
-    Math.ceil(selection.x + selection.width) <= Math.ceil(maxSelection.x + maxSelection.width) &&
-    Math.ceil(selection.y + selection.height) <= Math.ceil(maxSelection.y + maxSelection.height)
+    Math.round(selection.x) >= maxSelection.x &&
+    Math.round(selection.y) >= maxSelection.y &&
+    Math.round(selection.x + selection.width) <= Math.round(maxSelection.x + maxSelection.width) &&
+    Math.round(selection.y + selection.height) <= Math.round(maxSelection.y + maxSelection.height)
   );
 }
 
@@ -355,18 +355,22 @@ class MinMaxImageCropper extends ImageCropper {
       this.#cropperCanvasRect = this.cropperCanvas!.getBoundingClientRect();
 
       const maxImageWidth = Math.min(this.image!.width, this.maxSize.width);
-      const widthRatio = this.#cropperCanvasRect.width / maxImageWidth;
+      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 * widthRatio;
-      const maxWidth = this.maxSize.width * widthRatio;
+      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 (
-        selection.width < minWidth ||
-        selection.height < minHeight ||
-        selection.width > maxWidth ||
-        selection.height > maxHeight
+        Math.round(selection.width) < minWidth ||
+        Math.round(selection.height) < minHeight ||
+        Math.round(selection.width) > maxWidth ||
+        Math.round(selection.height) > maxHeight
       ) {
         event.preventDefault();
       }
@@ -387,20 +391,33 @@ class MinMaxImageCropper extends ImageCropper {
   }
 
   protected centerSelection(): void {
-    // Reset to get the maximum available height
+    // 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);
 
-    const dimensions = DomUtil.outerDimensions(this.cropperCanvas!.parentElement!);
-    this.cropperCanvas!.style.height = `${dimensions.height}px`;
+    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();
 
-    if (this.configuration.aspectRatio >= 1.0) {
-      this.cropperSelection!.$change(0, 0, this.#cropperCanvasRect.width, 0, this.configuration.aspectRatio, true);
-    } else {
-      this.cropperSelection!.$change(0, 0, 0, this.#cropperCanvasRect.height, this.configuration.aspectRatio, true);
-    }
+    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" });
   }
index 7631ca3083856c2ce302ec94f396bf9f417ff847..60bd94b1b2866782b4a61837597c6d1b8f31f922 100644 (file)
@@ -15,10 +15,10 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Image/Resizer", "WoltL
     exifreader_1 = tslib_1.__importDefault(exifreader_1);
     Util_1 = tslib_1.__importDefault(Util_1);
     function inSelection(selection, maxSelection) {
-        return (Math.ceil(selection.x) >= maxSelection.x &&
-            Math.ceil(selection.y) >= maxSelection.y &&
-            Math.ceil(selection.x + selection.width) <= Math.ceil(maxSelection.x + maxSelection.width) &&
-            Math.ceil(selection.y + selection.height) <= Math.ceil(maxSelection.y + maxSelection.height));
+        return (Math.round(selection.x) >= maxSelection.x &&
+            Math.round(selection.y) >= maxSelection.y &&
+            Math.round(selection.x + selection.width) <= Math.round(maxSelection.x + maxSelection.width) &&
+            Math.round(selection.y + selection.height) <= Math.round(maxSelection.y + maxSelection.height));
     }
     class ImageCropper {
         configuration;
@@ -267,15 +267,16 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Image/Resizer", "WoltL
                 const selection = event.detail;
                 this.#cropperCanvasRect = this.cropperCanvas.getBoundingClientRect();
                 const maxImageWidth = Math.min(this.image.width, this.maxSize.width);
-                const widthRatio = this.#cropperCanvasRect.width / maxImageWidth;
-                const minWidth = this.minSize.width * widthRatio;
-                const maxWidth = this.maxSize.width * widthRatio;
+                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 (selection.width < minWidth ||
-                    selection.height < minHeight ||
-                    selection.width > maxWidth ||
-                    selection.height > maxHeight) {
+                if (Math.round(selection.width) < minWidth ||
+                    Math.round(selection.height) < minHeight ||
+                    Math.round(selection.width) > maxWidth ||
+                    Math.round(selection.height) > maxHeight) {
                     event.preventDefault();
                 }
             });
@@ -292,18 +293,17 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Image/Resizer", "WoltL
             });
         }
         centerSelection() {
-            // Reset to get the maximum available height
+            // Reset to get the maximum available height and width
             this.cropperCanvas.style.height = "";
-            const dimensions = Util_1.default.outerDimensions(this.cropperCanvas.parentElement);
-            this.cropperCanvas.style.height = `${dimensions.height}px`;
+            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();
-            if (this.configuration.aspectRatio >= 1.0) {
-                this.cropperSelection.$change(0, 0, this.#cropperCanvasRect.width, 0, this.configuration.aspectRatio, true);
-            }
-            else {
-                this.cropperSelection.$change(0, 0, 0, this.#cropperCanvasRect.height, this.configuration.aspectRatio, true);
-            }
+            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" });
         }