Skip to content

Commit b1250d9

Browse files
committed
Merge branch 'file-upload-image-crop' into 6.2-user-coverphoto
2 parents 89143be + 1c6b805 commit b1250d9

File tree

5 files changed

+123
-39
lines changed

5 files changed

+123
-39
lines changed

ts/WoltLabSuite/Core/Component/Image/Cropper.ts

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ export interface CropperConfiguration {
2828

2929
function inSelection(selection: Selection, maxSelection: Selection): boolean {
3030
return (
31-
Math.ceil(selection.x) >= maxSelection.x &&
32-
Math.ceil(selection.y) >= maxSelection.y &&
33-
Math.ceil(selection.x + selection.width) <= Math.ceil(maxSelection.x + maxSelection.width) &&
34-
Math.ceil(selection.y + selection.height) <= Math.ceil(maxSelection.y + maxSelection.height)
31+
Math.round(selection.x) >= maxSelection.x &&
32+
Math.round(selection.y) >= maxSelection.y &&
33+
Math.round(selection.x + selection.width) <= Math.round(maxSelection.x + maxSelection.width) &&
34+
Math.round(selection.y + selection.height) <= Math.round(maxSelection.y + maxSelection.height)
3535
);
3636
}
3737

@@ -355,18 +355,22 @@ class MinMaxImageCropper extends ImageCropper {
355355
this.#cropperCanvasRect = this.cropperCanvas!.getBoundingClientRect();
356356

357357
const maxImageWidth = Math.min(this.image!.width, this.maxSize.width);
358-
const widthRatio = this.#cropperCanvasRect.width / maxImageWidth;
358+
const maxImageHeight = Math.min(this.image!.height, this.maxSize.height);
359+
const selectionRatio = Math.min(
360+
this.#cropperCanvasRect.width / maxImageWidth,
361+
this.#cropperCanvasRect.height / maxImageHeight,
362+
);
359363

360-
const minWidth = this.minSize.width * widthRatio;
361-
const maxWidth = this.maxSize.width * widthRatio;
364+
const minWidth = this.minSize.width * selectionRatio;
365+
const maxWidth = this.maxSize.width * selectionRatio;
362366
const minHeight = minWidth / this.configuration.aspectRatio;
363367
const maxHeight = maxWidth / this.configuration.aspectRatio;
364368

365369
if (
366-
selection.width < minWidth ||
367-
selection.height < minHeight ||
368-
selection.width > maxWidth ||
369-
selection.height > maxHeight
370+
Math.round(selection.width) < minWidth ||
371+
Math.round(selection.height) < minHeight ||
372+
Math.round(selection.width) > maxWidth ||
373+
Math.round(selection.height) > maxHeight
370374
) {
371375
event.preventDefault();
372376
}
@@ -387,20 +391,33 @@ class MinMaxImageCropper extends ImageCropper {
387391
}
388392

389393
protected centerSelection(): void {
390-
// Reset to get the maximum available height
394+
// Reset to get the maximum available height and width
391395
this.cropperCanvas!.style.height = "";
396+
this.cropperCanvas!.style.width = "";
397+
398+
const dimension = DomUtil.innerDimensions(this.cropperCanvas!.parentElement!);
399+
const ratio = Math.min(dimension.width / this.image!.width, dimension.height / this.image!.height);
392400

393-
const dimensions = DomUtil.outerDimensions(this.cropperCanvas!.parentElement!);
394-
this.cropperCanvas!.style.height = `${dimensions.height}px`;
401+
this.cropperCanvas!.style.height = `${this.image!.height * ratio}px`;
402+
this.cropperCanvas!.style.width = `${this.image!.width * ratio}px`;
395403

396404
this.cropperImage!.$center("contain");
397405
this.#cropperCanvasRect = this.cropperImage!.getBoundingClientRect();
398406

399-
if (this.configuration.aspectRatio >= 1.0) {
400-
this.cropperSelection!.$change(0, 0, this.#cropperCanvasRect.width, 0, this.configuration.aspectRatio, true);
401-
} else {
402-
this.cropperSelection!.$change(0, 0, 0, this.#cropperCanvasRect.height, this.configuration.aspectRatio, true);
403-
}
407+
const selectionRatio = Math.min(
408+
this.#cropperCanvasRect.width / this.maxSize.width,
409+
this.#cropperCanvasRect.height / this.maxSize.height,
410+
);
411+
412+
this.cropperSelection!.$change(
413+
0,
414+
0,
415+
this.maxSize.width * selectionRatio,
416+
this.maxSize.height * selectionRatio,
417+
this.configuration.aspectRatio,
418+
true,
419+
);
420+
404421
this.cropperSelection!.$center();
405422
this.cropperSelection!.scrollIntoView({ block: "center", inline: "center" });
406423
}

ts/WoltLabSuite/Core/Dom/Util.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,42 @@ const DomUtil = {
9696
return id;
9797
},
9898

99+
/**
100+
* Returns the inner height of an element including paddings.
101+
*/
102+
innerHeight(element: HTMLElement, styles?: CSSStyleDeclaration): number {
103+
styles = styles || window.getComputedStyle(element);
104+
105+
let height = element.clientHeight;
106+
height += ~~styles.paddingTop + ~~styles.paddingBottom;
107+
108+
return height;
109+
},
110+
111+
/**
112+
* Returns the inner width of an element including paddings.
113+
*/
114+
innerWidth(element: HTMLElement, styles?: CSSStyleDeclaration): number {
115+
styles = styles || window.getComputedStyle(element);
116+
117+
let width = element.clientWidth;
118+
width += ~~styles.paddingLeft + ~~styles.paddingRight;
119+
120+
return width;
121+
},
122+
123+
/**
124+
* Returns the inner dimensions of an element including paddings.
125+
*/
126+
innerDimensions(element: HTMLElement): Dimensions {
127+
const styles = window.getComputedStyle(element);
128+
129+
return {
130+
height: DomUtil.innerHeight(element, styles),
131+
width: DomUtil.innerWidth(element, styles),
132+
};
133+
},
134+
99135
/**
100136
* Returns the outer height of an element including margins.
101137
*/

wcfsetup/install/files/js/WoltLabSuite/Core/Component/Image/Cropper.js

Lines changed: 20 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wcfsetup/install/files/js/WoltLabSuite/Core/Dom/Util.js

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wcfsetup/install/files/style/ui/dialog.scss

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,9 @@ html[data-color-scheme="dark"] .dialog::backdrop {
469469
.dialog cropper-canvas {
470470
margin-left: auto;
471471
margin-right: auto;
472+
/* overwrites the default values of `min-height: 100px` and `min-width: 200px` */
473+
min-height: 1px;
474+
min-width: 1px;
472475
}
473476

474477
/* If the height of the image is many times greater than the width, a white area would be displayed at the bottom and/or top. */

0 commit comments

Comments
 (0)