Extracted xyresizer functions to system
This commit is contained in:
@@ -2,7 +2,12 @@ import { useRef, useEffect, memo } from 'react';
|
|||||||
import cc from 'classcat';
|
import cc from 'classcat';
|
||||||
import { drag } from 'd3-drag';
|
import { drag } from 'd3-drag';
|
||||||
import { select } from 'd3-selection';
|
import { select } from 'd3-selection';
|
||||||
import { getPointerPosition, clamp } from '@xyflow/system';
|
import {
|
||||||
|
getPointerPosition,
|
||||||
|
getControlDirection,
|
||||||
|
getDimensionsAfterResize,
|
||||||
|
getPositionAfterResize,
|
||||||
|
} from '@xyflow/system';
|
||||||
|
|
||||||
import { useStoreApi } from '../../hooks/useStore';
|
import { useStoreApi } from '../../hooks/useStore';
|
||||||
import { useNodeId } from '../../contexts/NodeIdContext';
|
import { useNodeId } from '../../contexts/NodeIdContext';
|
||||||
@@ -53,10 +58,7 @@ function ResizeControl({
|
|||||||
|
|
||||||
const selection = select(resizeControlRef.current);
|
const selection = select(resizeControlRef.current);
|
||||||
|
|
||||||
const enableX = controlPosition.includes('right') || controlPosition.includes('left');
|
const controlDirection = getControlDirection(controlPosition);
|
||||||
const enableY = controlPosition.includes('bottom') || controlPosition.includes('top');
|
|
||||||
const invertX = controlPosition.includes('left');
|
|
||||||
const invertY = controlPosition.includes('top');
|
|
||||||
|
|
||||||
const dragHandler = drag<HTMLDivElement, unknown>()
|
const dragHandler = drag<HTMLDivElement, unknown>()
|
||||||
.on('start', (event: ResizeDragEvent) => {
|
.on('start', (event: ResizeDragEvent) => {
|
||||||
@@ -82,61 +84,27 @@ function ResizeControl({
|
|||||||
})
|
})
|
||||||
.on('drag', (event: ResizeDragEvent) => {
|
.on('drag', (event: ResizeDragEvent) => {
|
||||||
const { nodeLookup, transform, snapGrid, snapToGrid, triggerNodeChanges } = store.getState();
|
const { nodeLookup, transform, snapGrid, snapToGrid, triggerNodeChanges } = store.getState();
|
||||||
const { xSnapped, ySnapped } = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
|
const pointerPosition = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
|
||||||
const node = nodeLookup.get(id);
|
const node = nodeLookup.get(id);
|
||||||
|
|
||||||
if (node) {
|
if (node) {
|
||||||
const changes: NodeChange[] = [];
|
const changes: NodeChange[] = [];
|
||||||
const {
|
|
||||||
pointerX: startX,
|
|
||||||
pointerY: startY,
|
|
||||||
width: startWidth,
|
|
||||||
height: startHeight,
|
|
||||||
x: startNodeX,
|
|
||||||
y: startNodeY,
|
|
||||||
aspectRatio,
|
|
||||||
} = startValues.current;
|
|
||||||
|
|
||||||
const { x: prevX, y: prevY, width: prevWidth, height: prevHeight } = prevValues.current;
|
const { x: prevX, y: prevY, width: prevWidth, height: prevHeight } = prevValues.current;
|
||||||
|
|
||||||
const distX = Math.floor(enableX ? xSnapped - startX : 0);
|
const { width, height } = getDimensionsAfterResize(
|
||||||
const distY = Math.floor(enableY ? ySnapped - startY : 0);
|
startValues.current,
|
||||||
|
controlDirection,
|
||||||
let width = clamp(startWidth + (invertX ? -distX : distX), minWidth, maxWidth);
|
pointerPosition,
|
||||||
let height = clamp(startHeight + (invertY ? -distY : distY), minHeight, maxHeight);
|
{ minWidth, minHeight, maxWidth, maxHeight },
|
||||||
|
keepAspectRatio
|
||||||
if (keepAspectRatio) {
|
);
|
||||||
const nextAspectRatio = width / height;
|
|
||||||
const isDiagonal = enableX && enableY;
|
|
||||||
const isHorizontal = enableX && !enableY;
|
|
||||||
const isVertical = enableY && !enableX;
|
|
||||||
|
|
||||||
width = (nextAspectRatio <= aspectRatio && isDiagonal) || isVertical ? height * aspectRatio : width;
|
|
||||||
height = (nextAspectRatio > aspectRatio && isDiagonal) || isHorizontal ? width / aspectRatio : height;
|
|
||||||
|
|
||||||
if (width >= maxWidth) {
|
|
||||||
width = maxWidth;
|
|
||||||
height = maxWidth / aspectRatio;
|
|
||||||
} else if (width <= minWidth) {
|
|
||||||
width = minWidth;
|
|
||||||
height = minWidth / aspectRatio;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (height >= maxHeight) {
|
|
||||||
height = maxHeight;
|
|
||||||
width = maxHeight * aspectRatio;
|
|
||||||
} else if (height <= minHeight) {
|
|
||||||
height = minHeight;
|
|
||||||
width = minHeight * aspectRatio;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const isWidthChange = width !== prevWidth;
|
const isWidthChange = width !== prevWidth;
|
||||||
const isHeightChange = height !== prevHeight;
|
const isHeightChange = height !== prevHeight;
|
||||||
|
|
||||||
if (invertX || invertY) {
|
if (controlDirection.affectsX || controlDirection.affectsY) {
|
||||||
const x = invertX ? startNodeX - (width - startWidth) : startNodeX;
|
const { x, y } = getPositionAfterResize(startValues.current, controlDirection, width, height);
|
||||||
const y = invertY ? startNodeY - (height - startHeight) : startNodeY;
|
|
||||||
|
|
||||||
// only transform the node if the width or height changes
|
// only transform the node if the width or height changes
|
||||||
const isXPosChange = x !== prevX && isWidthChange;
|
const isXPosChange = x !== prevX && isWidthChange;
|
||||||
@@ -184,8 +152,8 @@ function ResizeControl({
|
|||||||
prevWidth,
|
prevWidth,
|
||||||
height: prevValues.current.height,
|
height: prevValues.current.height,
|
||||||
prevHeight,
|
prevHeight,
|
||||||
invertX,
|
affectsX: controlDirection.affectsX,
|
||||||
invertY,
|
affectsY: controlDirection.affectsY,
|
||||||
});
|
});
|
||||||
|
|
||||||
const nextValues = { ...prevValues.current, direction };
|
const nextValues = { ...prevValues.current, direction };
|
||||||
|
|||||||
@@ -30,8 +30,6 @@
|
|||||||
let _minHeight = minHeight || 10;
|
let _minHeight = minHeight || 10;
|
||||||
let _maxWidth = maxWidth || Number.MAX_VALUE;
|
let _maxWidth = maxWidth || Number.MAX_VALUE;
|
||||||
let _maxHeight = maxHeight || Number.MAX_VALUE;
|
let _maxHeight = maxHeight || Number.MAX_VALUE;
|
||||||
|
|
||||||
$: console.log(isVisible);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if isVisible}
|
{#if isVisible}
|
||||||
|
|||||||
@@ -7,8 +7,11 @@
|
|||||||
import {
|
import {
|
||||||
ResizeControlVariant,
|
ResizeControlVariant,
|
||||||
getPointerPosition,
|
getPointerPosition,
|
||||||
clamp,
|
getResizeDirection,
|
||||||
getResizeDirection
|
getControlDirection,
|
||||||
|
type XYResizeControlPosition,
|
||||||
|
getDimensionsAfterResize,
|
||||||
|
getPositionAfterResize
|
||||||
} from '@xyflow/system';
|
} from '@xyflow/system';
|
||||||
import { useStore } from '$lib/store';
|
import { useStore } from '$lib/store';
|
||||||
|
|
||||||
@@ -52,7 +55,9 @@
|
|||||||
let startValues = { ...initStartValues };
|
let startValues = { ...initStartValues };
|
||||||
let prevValues = { ...initPrevValues };
|
let prevValues = { ...initPrevValues };
|
||||||
|
|
||||||
$: defaultPosition = variant === ResizeControlVariant.Line ? 'right' : 'bottom-right';
|
$: defaultPosition = (
|
||||||
|
variant === ResizeControlVariant.Line ? 'right' : 'bottom-right'
|
||||||
|
) as XYResizeControlPosition;
|
||||||
$: controlPosition = position ?? defaultPosition;
|
$: controlPosition = position ?? defaultPosition;
|
||||||
|
|
||||||
$: positionClassNames = controlPosition.split('-');
|
$: positionClassNames = controlPosition.split('-');
|
||||||
@@ -67,10 +72,7 @@
|
|||||||
}
|
}
|
||||||
const selection = select(resizeControlRef);
|
const selection = select(resizeControlRef);
|
||||||
|
|
||||||
const enableX = controlPosition.includes('right') || controlPosition.includes('left');
|
const controlDirection = getControlDirection(controlPosition);
|
||||||
const enableY = controlPosition.includes('bottom') || controlPosition.includes('top');
|
|
||||||
const invertX = controlPosition.includes('left');
|
|
||||||
const invertY = controlPosition.includes('top');
|
|
||||||
|
|
||||||
const dragHandler = drag<HTMLDivElement, unknown>()
|
const dragHandler = drag<HTMLDivElement, unknown>()
|
||||||
.on('start', (event: ResizeDragEvent) => {
|
.on('start', (event: ResizeDragEvent) => {
|
||||||
@@ -98,7 +100,7 @@
|
|||||||
onResizeStart?.(event, { ...prevValues });
|
onResizeStart?.(event, { ...prevValues });
|
||||||
})
|
})
|
||||||
.on('drag', (event: ResizeDragEvent) => {
|
.on('drag', (event: ResizeDragEvent) => {
|
||||||
const { xSnapped, ySnapped } = getPointerPosition(event.sourceEvent, {
|
const pointerPosition = getPointerPosition(event.sourceEvent, {
|
||||||
transform: [$viewport.x, $viewport.y, $viewport.zoom],
|
transform: [$viewport.x, $viewport.y, $viewport.zoom],
|
||||||
snapGrid: $snapGrid ?? undefined,
|
snapGrid: $snapGrid ?? undefined,
|
||||||
snapToGrid: !!$snapGrid
|
snapToGrid: !!$snapGrid
|
||||||
@@ -106,64 +108,27 @@
|
|||||||
const node = $nodeLookup.get(id);
|
const node = $nodeLookup.get(id);
|
||||||
|
|
||||||
if (node) {
|
if (node) {
|
||||||
const {
|
|
||||||
pointerX: startX,
|
|
||||||
pointerY: startY,
|
|
||||||
width: startWidth,
|
|
||||||
height: startHeight,
|
|
||||||
x: startNodeX,
|
|
||||||
y: startNodeY,
|
|
||||||
aspectRatio
|
|
||||||
} = startValues;
|
|
||||||
|
|
||||||
const { x: prevX, y: prevY, width: prevWidth, height: prevHeight } = prevValues;
|
const { x: prevX, y: prevY, width: prevWidth, height: prevHeight } = prevValues;
|
||||||
|
|
||||||
const distX = Math.floor(enableX ? xSnapped - startX : 0);
|
const { width, height } = getDimensionsAfterResize(
|
||||||
const distY = Math.floor(enableY ? ySnapped - startY : 0);
|
startValues,
|
||||||
|
controlDirection,
|
||||||
let width = clamp(startWidth + (invertX ? -distX : distX), minWidth, maxWidth);
|
pointerPosition,
|
||||||
let height = clamp(startHeight + (invertY ? -distY : distY), minHeight, maxHeight);
|
{
|
||||||
|
minWidth: _minWidth,
|
||||||
if (keepAspectRatio) {
|
minHeight: _minHeight,
|
||||||
const nextAspectRatio = width / height;
|
maxWidth: _maxWidth,
|
||||||
const isDiagonal = enableX && enableY;
|
maxHeight: _maxHeight
|
||||||
const isHorizontal = enableX && !enableY;
|
},
|
||||||
const isVertical = enableY && !enableX;
|
!!keepAspectRatio
|
||||||
|
);
|
||||||
width =
|
|
||||||
(nextAspectRatio <= aspectRatio && isDiagonal) || isVertical
|
|
||||||
? height * aspectRatio
|
|
||||||
: width;
|
|
||||||
height =
|
|
||||||
(nextAspectRatio > aspectRatio && isDiagonal) || isHorizontal
|
|
||||||
? width / aspectRatio
|
|
||||||
: height;
|
|
||||||
|
|
||||||
if (width >= _maxWidth) {
|
|
||||||
width = _maxWidth;
|
|
||||||
height = _maxWidth / aspectRatio;
|
|
||||||
} else if (width <= _minWidth) {
|
|
||||||
width = _minWidth;
|
|
||||||
height = _minWidth / aspectRatio;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (height >= _maxHeight) {
|
|
||||||
height = _maxHeight;
|
|
||||||
width = _maxHeight * aspectRatio;
|
|
||||||
} else if (height <= _minHeight) {
|
|
||||||
height = _minHeight;
|
|
||||||
width = _minHeight * aspectRatio;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const isWidthChange = width !== prevWidth;
|
const isWidthChange = width !== prevWidth;
|
||||||
const isHeightChange = height !== prevHeight;
|
const isHeightChange = height !== prevHeight;
|
||||||
|
|
||||||
let changes = false;
|
let changes = false;
|
||||||
|
|
||||||
if (invertX || invertY) {
|
if (controlDirection.affectsX || controlDirection.affectsY) {
|
||||||
const x = invertX ? startNodeX - (width - startWidth) : startNodeX;
|
const { x, y } = getPositionAfterResize(startValues, controlDirection, width, height);
|
||||||
const y = invertY ? startNodeY - (height - startHeight) : startNodeY;
|
|
||||||
|
|
||||||
// only transform the node if the width or height changes
|
// only transform the node if the width or height changes
|
||||||
const isXPosChange = x !== prevX && isWidthChange;
|
const isXPosChange = x !== prevX && isWidthChange;
|
||||||
@@ -199,8 +164,8 @@
|
|||||||
prevWidth,
|
prevWidth,
|
||||||
height: prevValues.height,
|
height: prevValues.height,
|
||||||
prevHeight,
|
prevHeight,
|
||||||
invertX,
|
affectsX: controlDirection.affectsX,
|
||||||
invertY
|
affectsY: controlDirection.affectsY
|
||||||
});
|
});
|
||||||
|
|
||||||
const nextValues = { ...prevValues, direction };
|
const nextValues = { ...prevValues, direction };
|
||||||
|
|||||||
@@ -1,76 +1,2 @@
|
|||||||
export type { D3DragEvent, SubjectPosition } from 'd3-drag';
|
export * from './types';
|
||||||
|
export * from './utils';
|
||||||
export type XYResizeParams = {
|
|
||||||
x: number;
|
|
||||||
y: number;
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type XYResizeParamsWithDirection = XYResizeParams & {
|
|
||||||
direction: number[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type XYResizeControlLinePosition = 'top' | 'bottom' | 'left' | 'right';
|
|
||||||
|
|
||||||
export type XYResizeControlPosition =
|
|
||||||
| XYResizeControlLinePosition
|
|
||||||
| 'top-left'
|
|
||||||
| 'top-right'
|
|
||||||
| 'bottom-left'
|
|
||||||
| 'bottom-right';
|
|
||||||
|
|
||||||
export enum ResizeControlVariant {
|
|
||||||
Line = 'line',
|
|
||||||
Handle = 'handle',
|
|
||||||
}
|
|
||||||
|
|
||||||
export const XY_RESIZER_HANDLE_CONTROLS: XYResizeControlPosition[] = [
|
|
||||||
'top-left',
|
|
||||||
'top-right',
|
|
||||||
'bottom-left',
|
|
||||||
'bottom-right',
|
|
||||||
];
|
|
||||||
export const XY_RESIZER_LINE_CONTROLS: XYResizeControlLinePosition[] = ['top', 'right', 'bottom', 'left'];
|
|
||||||
|
|
||||||
type GetResizeDirectionParams = {
|
|
||||||
width: number;
|
|
||||||
prevWidth: number;
|
|
||||||
height: number;
|
|
||||||
prevHeight: number;
|
|
||||||
invertX: boolean;
|
|
||||||
invertY: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all connecting edges for a given set of nodes
|
|
||||||
* @param width - new width of the node
|
|
||||||
* @param prevWidth - previous width of the node
|
|
||||||
* @param height - new height of the node
|
|
||||||
* @param prevHeight - previous height of the node
|
|
||||||
* @param invertX - whether to invert the resize direction for the x axis
|
|
||||||
* @param invertY - whether to invert the resize direction for the y axis
|
|
||||||
* @returns array of two numbers representing the direction of the resize for each axis, 0 = no change, 1 = increase, -1 = decrease
|
|
||||||
*/
|
|
||||||
export function getResizeDirection({
|
|
||||||
width,
|
|
||||||
prevWidth,
|
|
||||||
height,
|
|
||||||
prevHeight,
|
|
||||||
invertX,
|
|
||||||
invertY,
|
|
||||||
}: GetResizeDirectionParams) {
|
|
||||||
const deltaWidth = width - prevWidth;
|
|
||||||
const deltaHeight = height - prevHeight;
|
|
||||||
|
|
||||||
const direction = [deltaWidth > 0 ? 1 : deltaWidth < 0 ? -1 : 0, deltaHeight > 0 ? 1 : deltaHeight < 0 ? -1 : 0];
|
|
||||||
|
|
||||||
if (deltaWidth && invertX) {
|
|
||||||
direction[0] = direction[0] * -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deltaHeight && invertY) {
|
|
||||||
direction[1] = direction[1] * -1;
|
|
||||||
}
|
|
||||||
return direction;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
export type { D3DragEvent, SubjectPosition } from 'd3-drag';
|
||||||
|
|
||||||
|
export type XYResizeParams = {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type XYResizeParamsWithDirection = XYResizeParams & {
|
||||||
|
direction: number[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type XYResizeControlLinePosition = 'top' | 'bottom' | 'left' | 'right';
|
||||||
|
|
||||||
|
export type XYResizeControlPosition =
|
||||||
|
| XYResizeControlLinePosition
|
||||||
|
| 'top-left'
|
||||||
|
| 'top-right'
|
||||||
|
| 'bottom-left'
|
||||||
|
| 'bottom-right';
|
||||||
|
|
||||||
|
export enum ResizeControlVariant {
|
||||||
|
Line = 'line',
|
||||||
|
Handle = 'handle',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const XY_RESIZER_HANDLE_CONTROLS: XYResizeControlPosition[] = [
|
||||||
|
'top-left',
|
||||||
|
'top-right',
|
||||||
|
'bottom-left',
|
||||||
|
'bottom-right',
|
||||||
|
];
|
||||||
|
export const XY_RESIZER_LINE_CONTROLS: XYResizeControlLinePosition[] = ['top', 'right', 'bottom', 'left'];
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
import { clamp, getPointerPosition } from '../utils';
|
||||||
|
import { XYResizeControlPosition } from './types';
|
||||||
|
|
||||||
|
type GetResizeDirectionParams = {
|
||||||
|
width: number;
|
||||||
|
prevWidth: number;
|
||||||
|
height: number;
|
||||||
|
prevHeight: number;
|
||||||
|
affectsX: boolean;
|
||||||
|
affectsY: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all connecting edges for a given set of nodes
|
||||||
|
* @param width - new width of the node
|
||||||
|
* @param prevWidth - previous width of the node
|
||||||
|
* @param height - new height of the node
|
||||||
|
* @param prevHeight - previous height of the node
|
||||||
|
* @param affectsX - whether to invert the resize direction for the x axis
|
||||||
|
* @param affectsY - whether to invert the resize direction for the y axis
|
||||||
|
* @returns array of two numbers representing the direction of the resize for each axis, 0 = no change, 1 = increase, -1 = decrease
|
||||||
|
*/
|
||||||
|
export function getResizeDirection({
|
||||||
|
width,
|
||||||
|
prevWidth,
|
||||||
|
height,
|
||||||
|
prevHeight,
|
||||||
|
affectsX,
|
||||||
|
affectsY,
|
||||||
|
}: GetResizeDirectionParams) {
|
||||||
|
const deltaWidth = width - prevWidth;
|
||||||
|
const deltaHeight = height - prevHeight;
|
||||||
|
|
||||||
|
const direction = [deltaWidth > 0 ? 1 : deltaWidth < 0 ? -1 : 0, deltaHeight > 0 ? 1 : deltaHeight < 0 ? -1 : 0];
|
||||||
|
|
||||||
|
if (deltaWidth && affectsX) {
|
||||||
|
direction[0] = direction[0] * -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deltaHeight && affectsY) {
|
||||||
|
direction[1] = direction[1] * -1;
|
||||||
|
}
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the control position that is being dragged to dimensions that are being resized
|
||||||
|
* @param controlPosition - position of the control that is being dragged
|
||||||
|
* @returns isHorizontal, isVertical, affectsX, affectsY,
|
||||||
|
*/
|
||||||
|
export function getControlDirection(controlPosition: XYResizeControlPosition) {
|
||||||
|
const isHorizontal = controlPosition.includes('right') || controlPosition.includes('left');
|
||||||
|
const isVertical = controlPosition.includes('bottom') || controlPosition.includes('top');
|
||||||
|
const affectsX = controlPosition.includes('left');
|
||||||
|
const affectsY = controlPosition.includes('top');
|
||||||
|
|
||||||
|
return {
|
||||||
|
isHorizontal,
|
||||||
|
isVertical,
|
||||||
|
affectsX,
|
||||||
|
affectsY,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
type PrevValues = {
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type StartValues = PrevValues & {
|
||||||
|
pointerX: number;
|
||||||
|
pointerY: number;
|
||||||
|
aspectRatio: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates new width & height of node after resize based on pointer position
|
||||||
|
* @param startValues - starting values of resize
|
||||||
|
* @param controlDirection - dimensions affected by the resize
|
||||||
|
* @param pointerPosition - the current pointer position corrected for snapping
|
||||||
|
* @param boundries - maximum and minimum dimensions of the node
|
||||||
|
* @param keepAspectRatio - prevent changes of asprect ratio
|
||||||
|
* @returns width: new width of node, height: new height of node
|
||||||
|
*/
|
||||||
|
export function getDimensionsAfterResize(
|
||||||
|
startValues: StartValues,
|
||||||
|
controlDirection: ReturnType<typeof getControlDirection>,
|
||||||
|
pointerPosition: ReturnType<typeof getPointerPosition>,
|
||||||
|
boundries: { minWidth: number; maxWidth: number; minHeight: number; maxHeight: number },
|
||||||
|
keepAspectRatio: boolean
|
||||||
|
) {
|
||||||
|
const { isHorizontal, isVertical, affectsX, affectsY } = controlDirection;
|
||||||
|
const { xSnapped, ySnapped } = pointerPosition;
|
||||||
|
const { minWidth, maxWidth, minHeight, maxHeight } = boundries;
|
||||||
|
|
||||||
|
const { pointerX: startX, pointerY: startY, width: startWidth, height: startHeight, aspectRatio } = startValues;
|
||||||
|
const distX = Math.floor(isHorizontal ? xSnapped - startX : 0);
|
||||||
|
const distY = Math.floor(isVertical ? ySnapped - startY : 0);
|
||||||
|
|
||||||
|
let width = clamp(startWidth + (affectsX ? -distX : distX), minWidth, maxWidth);
|
||||||
|
let height = clamp(startHeight + (affectsY ? -distY : distY), minHeight, maxHeight);
|
||||||
|
|
||||||
|
if (keepAspectRatio) {
|
||||||
|
const nextAspectRatio = width / height;
|
||||||
|
const isDiagonal = isHorizontal && isVertical;
|
||||||
|
const isOnlyHorizontal = isHorizontal && !isVertical;
|
||||||
|
const isOnlyVertical = isVertical && !isHorizontal;
|
||||||
|
|
||||||
|
width = (nextAspectRatio <= aspectRatio && isDiagonal) || isOnlyVertical ? height * aspectRatio : width;
|
||||||
|
height = (nextAspectRatio > aspectRatio && isDiagonal) || isOnlyHorizontal ? width / aspectRatio : height;
|
||||||
|
|
||||||
|
if (width >= maxWidth) {
|
||||||
|
width = maxWidth;
|
||||||
|
height = maxWidth / aspectRatio;
|
||||||
|
} else if (width <= minWidth) {
|
||||||
|
width = minWidth;
|
||||||
|
height = minWidth / aspectRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (height >= maxHeight) {
|
||||||
|
height = maxHeight;
|
||||||
|
width = maxHeight * aspectRatio;
|
||||||
|
} else if (height <= minHeight) {
|
||||||
|
height = minHeight;
|
||||||
|
width = minHeight * aspectRatio;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines new x & y position of node after resize based on new width & height
|
||||||
|
* @param startValues - starting values of resize
|
||||||
|
* @param controlDirection - dimensions affected by the resize
|
||||||
|
* @param width - new width of node
|
||||||
|
* @param height - new height of node
|
||||||
|
* @returns x: new x position of node, y: new y position of node
|
||||||
|
*/
|
||||||
|
export function getPositionAfterResize(
|
||||||
|
startValues: StartValues,
|
||||||
|
controlDirection: ReturnType<typeof getControlDirection>,
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
) {
|
||||||
|
const x = controlDirection.affectsX ? startValues.x - (width - startValues.width) : startValues.x;
|
||||||
|
const y = controlDirection.affectsY ? startValues.y - (height - startValues.height) : startValues.y;
|
||||||
|
return { x, y };
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user