@@ -0,0 +1,24 @@
|
||||
export function calcNewSizeFromAspectRatio(
|
||||
aspectRatio: number | null,
|
||||
oldWidth: number,
|
||||
oldHeight: number
|
||||
) {
|
||||
let newWidth = oldWidth;
|
||||
let newHeight = oldHeight;
|
||||
|
||||
if (aspectRatio) {
|
||||
if (oldHeight * aspectRatio > oldWidth) {
|
||||
newHeight = oldWidth / aspectRatio;
|
||||
} else {
|
||||
newWidth = oldHeight * aspectRatio;
|
||||
}
|
||||
}
|
||||
|
||||
return {width: Math.floor(newWidth), height: Math.floor(newHeight)};
|
||||
}
|
||||
|
||||
export function aspectRatioFromStr(ratio: string | null): number | null {
|
||||
if (!ratio) return null;
|
||||
const parts = ratio.split(':');
|
||||
return parseInt(parts[0]) / parseInt(parts[1]);
|
||||
}
|
||||
30
common/resources/client/ui/interactions/utils/center-within-boundary.ts
Executable file
30
common/resources/client/ui/interactions/utils/center-within-boundary.ts
Executable file
@@ -0,0 +1,30 @@
|
||||
import {InteractableRect} from '../interactable-event';
|
||||
import {calcNewSizeFromAspectRatio} from './calc-new-size-from-aspect-ratio';
|
||||
|
||||
export function centerWithinBoundary(
|
||||
boundary: Omit<InteractableRect, 'angle'>,
|
||||
aspectRatio: number | null = null
|
||||
): InteractableRect {
|
||||
// set rect to the size of specified boundary
|
||||
const rect: InteractableRect = {
|
||||
width: boundary.width,
|
||||
height: boundary.height,
|
||||
top: 0,
|
||||
left: 0,
|
||||
angle: 0,
|
||||
};
|
||||
// maybe resize rect based on aspect ratio
|
||||
if (aspectRatio) {
|
||||
const newSize = calcNewSizeFromAspectRatio(
|
||||
aspectRatio,
|
||||
rect.width,
|
||||
rect.height
|
||||
);
|
||||
rect.width = newSize.width;
|
||||
rect.height = newSize.height;
|
||||
}
|
||||
// center the rect
|
||||
rect.left = (boundary.width - rect.width) / 2;
|
||||
rect.top = (boundary.height - rect.height) / 2;
|
||||
return rect;
|
||||
}
|
||||
10
common/resources/client/ui/interactions/utils/dom-rect-to-obj.ts
Executable file
10
common/resources/client/ui/interactions/utils/dom-rect-to-obj.ts
Executable file
@@ -0,0 +1,10 @@
|
||||
import {InteractableRect} from '../interactable-event';
|
||||
|
||||
export function domRectToObj(rect: DOMRect): InteractableRect {
|
||||
return {
|
||||
left: rect.left,
|
||||
top: rect.top,
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
};
|
||||
}
|
||||
19
common/resources/client/ui/interactions/utils/interactable-rect-from-el.ts
Executable file
19
common/resources/client/ui/interactions/utils/interactable-rect-from-el.ts
Executable file
@@ -0,0 +1,19 @@
|
||||
import {InteractableRect} from '../interactable-event';
|
||||
|
||||
export function interactableRectFromEl(el: HTMLElement) {
|
||||
const translateStr = el.style.transform.match(/translate\((.+?)\)/)?.[1];
|
||||
const translateValues = (translateStr || '').split(',');
|
||||
const top = translateValues[1] || '0';
|
||||
const left = translateValues[0] || '0';
|
||||
|
||||
const rect: InteractableRect = {
|
||||
width: el.offsetWidth,
|
||||
height: el.offsetHeight,
|
||||
left: parseInt(left),
|
||||
top: parseInt(top),
|
||||
angle: 0,
|
||||
};
|
||||
const initialAspectRatio = rect.width / rect.height;
|
||||
|
||||
return {rect, initialAspectRatio};
|
||||
}
|
||||
14
common/resources/client/ui/interactions/utils/rects-intersect.ts
Executable file
14
common/resources/client/ui/interactions/utils/rects-intersect.ts
Executable file
@@ -0,0 +1,14 @@
|
||||
import {InteractableRect} from '../interactable-event';
|
||||
|
||||
export function rectsIntersect(
|
||||
rectA?: InteractableRect,
|
||||
rectB?: InteractableRect
|
||||
) {
|
||||
if (!rectA || !rectB) return false;
|
||||
return (
|
||||
rectA.left <= rectB.left + rectB.width &&
|
||||
rectA.left + rectA.width >= rectB.left &&
|
||||
rectA.top <= rectB.top + rectB.height &&
|
||||
rectA.top + rectA.height >= rectB.top
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import {InteractableRect} from '../interactable-event';
|
||||
|
||||
export function restrictResizableWithinBoundary(
|
||||
rect: InteractableRect,
|
||||
boundaryRect: InteractableRect
|
||||
) {
|
||||
const boundedRect = {...rect};
|
||||
|
||||
// restrict to left edge of boundary
|
||||
boundedRect.left = Math.max(0, boundedRect.left);
|
||||
// compensate width when left is bounded
|
||||
const leftRestriction = boundedRect.left - rect.left;
|
||||
if (leftRestriction > 0) {
|
||||
boundedRect.width -= leftRestriction;
|
||||
}
|
||||
|
||||
// restrict to top edge of boundary
|
||||
boundedRect.top = Math.max(0, boundedRect.top);
|
||||
// compensate height when top is bounded
|
||||
const topRestriction = boundedRect.top - rect.top;
|
||||
if (topRestriction > 0) {
|
||||
boundedRect.height -= topRestriction;
|
||||
}
|
||||
|
||||
// restrict to right edge of boundary
|
||||
boundedRect.width = Math.min(
|
||||
boundedRect.width,
|
||||
boundaryRect.width - boundedRect.left
|
||||
);
|
||||
|
||||
// restrict to bottom edge of boundary
|
||||
boundedRect.height = Math.min(
|
||||
boundedRect.height,
|
||||
boundaryRect.height - boundedRect.top
|
||||
);
|
||||
|
||||
return boundedRect;
|
||||
}
|
||||
Reference in New Issue
Block a user