Skip to content

Commit

Permalink
Adapt to resize algorithm changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Norserium committed Oct 26, 2022
1 parent 1da1ecf commit a26949e
Show file tree
Hide file tree
Showing 11 changed files with 218 additions and 63 deletions.
4 changes: 4 additions & 0 deletions example/docs/algorithms/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"label": "Algorithms",
"position": 7
}
11 changes: 11 additions & 0 deletions example/docs/algorithms/resize-algorithm.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
title: Resize Algorithm
sidebar_position: 7
---
import { ResizeAlgorithm } from '../../src/components/algorithms/ResizeAlgorithm';

# Advanced Recipes

## Resize Algorithm

<ResizeAlgorithm/>
15 changes: 4 additions & 11 deletions example/docs/tutorials/custom-stencil.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -391,17 +391,10 @@ export const CircleStencil = forwardRef<StencilRef, StencilProps>(
}));

const onResize = (shift: MoveDirections) => {
cropper.resizeCoordinates(
{
left: -shift.top,
right: -shift.top,
top: -shift.top,
bottom: -shift.top,
},
{
compensate: true,
},
);
cropper.resizeCoordinates('center', {
left: shift.left,
top: shift.left,
});
};

const onMove = (directions: MoveDirections) => {
Expand Down
18 changes: 18 additions & 0 deletions example/src/components/algorithms/ResizeAlgorithm/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.resize-algorithm {
width: 100%;
height: 400px;
&__boundary {
position: relative;
}
&__stencil {
position: absolute;
color: var(--ifm-color-primary);
&-line {
border-color: var(--ifm-color-primary);
}
}
&__reference {
position: absolute;
border: solid 1px var(--ifm-color-primary-dark)
}
}
124 changes: 124 additions & 0 deletions example/src/components/algorithms/ResizeAlgorithm/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import React, { useEffect, useRef, useState } from 'react';
import { BoundingBox } from 'react-advanced-cropper';
import './index.scss';
import { coordinatesToStyle } from '@site/src/components/algorithms/utils';
import {
approximateSize,
Coordinates,
createAspectRatio,
moveToPositionRestrictions,
anchoredResizeCoordinatesAlgorithm,
ResizeOptions,
} from 'advanced-cropper';
import { useWindowResize } from '../../../service/useWindowResize';

export const ResizeAlgorithm = () => {
const exampleRef = useRef<HTMLDivElement>(null);

const [aspectRatio] = useState(1);
const [boundary, setBoundary] = useState({ width: 0, height: 0 });
const [coordinates, setCoordinates] = useState({ width: 100, height: 100, left: 0, top: 0 });

const [reference, setReference] = useState<Coordinates | null>(null);

const coordinatesStyle = coordinatesToStyle(coordinates);
const referenceStyle = coordinatesToStyle(reference);

const onResize = (anchor, directions, options: ResizeOptions) => {
setReference(options.reference || null);
setCoordinates(
anchoredResizeCoordinatesAlgorithm(coordinates, anchor, directions, options, {
aspectRatio: createAspectRatio(aspectRatio),
sizeRestrictions: {
maxWidth: boundary.width,
maxHeight: boundary.height,
minWidth: 0,
minHeight: 0,
},
positionRestrictions: {
left: 0,
top: 0,
right: boundary.width,
bottom: boundary.height,
},
}),
);
};

const onResizeEnd = () => {
setReference(null);
};

const updateBoundary = () => {
if (exampleRef.current) {
const updatedBoundary = {
width: exampleRef.current.clientWidth,
height: exampleRef.current.clientHeight,
};
setBoundary(updatedBoundary);
setCoordinates((coordinates) => {
if (coordinates) {
const updatedCoordinates = {
...coordinates,
...approximateSize({
width: coordinates.width,
height: coordinates.height,
aspectRatio,
sizeRestrictions: {
maxWidth: updatedBoundary.width,
maxHeight: updatedBoundary.height,
minHeight: 0,
minWidth: 0,
},
}),
};
return moveToPositionRestrictions(updatedCoordinates, {
left: 0,
top: 0,
bottom: updatedBoundary.height,
right: updatedBoundary.width,
});
}
return coordinates;
});
}
};

useWindowResize(updateBoundary);

useEffect(() => {
if (exampleRef.current) {
setCoordinates({
width: 100,
height: 100,
left: exampleRef.current.clientWidth / 2 - 50,
top: exampleRef.current.clientHeight / 2 - 50,
});
}
updateBoundary();
}, []);

return (
<div className={'resize-algorithm'} ref={exampleRef}>
<div
className={'resize-algorithm__boundary'}
style={{
width: `${boundary.width}px`,
height: `${boundary.height}px`,
}}
>
<BoundingBox
reference={coordinates}
style={coordinatesStyle}
className={'resize-algorithm__stencil'}
onResize={onResize}
onResizeEnd={onResizeEnd}
lineClassNames={{
default: 'resize-algorithm__stencil-line',
}}
/>
<div className={'resize-algorithm__reference'} style={referenceStyle} />
</div>
</div>
);
};
12 changes: 12 additions & 0 deletions example/src/components/algorithms/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Coordinates } from 'advanced-cropper';

export function coordinatesToStyle(coordinates: Coordinates | null) {
return coordinates
? {
width: `${coordinates.width}px`,
height: `${coordinates.height}px`,
left: `${coordinates.left}px`,
top: `${coordinates.top}px`,
}
: {};
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,10 @@ export const CircleStencil = forwardRef<StencilRef, StencilProps>(({ cropper }:
}));

const onResize = (shift: MoveDirections) => {
cropper.resizeCoordinates(
{
left: -shift.top,
right: -shift.top,
top: -shift.top,
bottom: -shift.top,
},
{
compensate: true,
},
);
cropper.resizeCoordinates('center', {
left: shift.left,
top: shift.left,
});
};

const onMove = (directions: MoveDirections) => {
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-advanced-cropper",
"version": "0.14.0",
"version": "0.15.0",
"description": "The react cropper library that gives the possibility to create croppers exactly suited for your website design",
"author": "Norserium",
"license": "MIT",
Expand Down Expand Up @@ -78,7 +78,7 @@
"dist"
],
"dependencies": {
"advanced-cropper": "0.14.0",
"advanced-cropper": "0.15.0",
"classnames": "^2.2.6",
"tslib": "^2.4.0"
},
Expand Down
59 changes: 29 additions & 30 deletions src/components/service/BoundingBox.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import React, { ComponentType, useMemo, ReactNode, CSSProperties } from 'react';
import React, { ComponentType, useMemo, ReactNode, CSSProperties, useState } from 'react';
import classnames from 'classnames';
import cn from 'classnames';
import {
CardinalDirection,
OrdinalDirection,
HorizontalCardinalDirection,
VerticalCardinalDirection,
ResizeDirections,
MoveDirections,
ResizeOptions,
getDirectionNames,
isCardinalDirection,
isObject,
Coordinates,
ResizeAnchor,
} from 'advanced-cropper';
import { SimpleLine } from '../lines/SimpleLine';
import { SimpleHandler } from '../handlers/SimpleHandler';
Expand Down Expand Up @@ -47,9 +48,10 @@ interface Props {
lineClassNames?: LineClassNames;
lineWrapperClassNames?: LineClassNames;
disabled?: boolean;
onResize?: (directions: ResizeDirections, options: ResizeOptions) => void;
onResize?: (anchor: ResizeAnchor, directions: MoveDirections, options: ResizeOptions) => void;
onResizeEnd?: () => void;
children?: ReactNode;
reference?: Coordinates | null;
}

interface HandlerNode {
Expand Down Expand Up @@ -113,7 +115,10 @@ export const BoundingBox = ({
lineClassNames = {},
lineWrapperClassNames = {},
disabled = false,
reference = null,
}: Props) => {
const [lastReference, setLastReference] = useState<Coordinates | null>(null);

const points = useMemo(() => {
const result: PointNode[] = [];
HORIZONTAL_DIRECTIONS.forEach((hDirection) => {
Expand Down Expand Up @@ -198,23 +203,10 @@ export const BoundingBox = ({
) =>
({ left, top }: MoveDirections, nativeEvent: MouseEvent | TouchEvent) => {
const directions = {
left: 0,
right: 0,
top: 0,
bottom: 0,
left,
top,
};

if (horizontalDirection === 'west') {
directions.left -= left;
} else if (horizontalDirection === 'east') {
directions.right += left;
}
if (verticalDirection === 'north') {
directions.top -= top;
} else if (verticalDirection === 'south') {
directions.bottom += top;
}

let respectDirection: 'width' | 'height' | undefined;
if (!verticalDirection && horizontalDirection) {
respectDirection = 'width';
Expand All @@ -224,20 +216,27 @@ export const BoundingBox = ({

if (!disabled) {
if (onResize) {
onResize(directions, {
allowedDirections: {
left: horizontalDirection === 'west' || !horizontalDirection,
right: horizontalDirection === 'east' || !horizontalDirection,
bottom: verticalDirection === 'south' || !verticalDirection,
top: verticalDirection === 'north' || !verticalDirection,
},
preserveAspectRatio: nativeEvent && nativeEvent.shiftKey,
respectDirection,
});
const anchor = getDirectionNames(horizontalDirection, verticalDirection).camelCase;
if (anchor) {
onResize(anchor, directions, {
reference: lastReference || reference,
preserveAspectRatio: nativeEvent && nativeEvent.shiftKey,
respectDirection,
compensate: true,
});
}
}
if (!lastReference) {
setLastReference(reference);
}
}
};

const onHandlerDragEnd = () => {
onResizeEnd?.();
setLastReference(null);
};

return (
<div className={cn('advanced-cropper-bounding-box', className)} style={style}>
{children}
Expand All @@ -251,7 +250,7 @@ export const BoundingBox = ({
position={line.name}
disabled={line.disabled}
onDrag={onHandlerDrag(line.horizontalPosition, line.verticalPosition)}
onDragEnd={onResizeEnd}
onDragEnd={onHandlerDragEnd}
/>
))}
</div>
Expand All @@ -266,7 +265,7 @@ export const BoundingBox = ({
verticalPosition={handler.verticalPosition}
disabled={handler.disabled}
onDrag={onHandlerDrag(handler.horizontalPosition, handler.verticalPosition)}
onDragEnd={onResizeEnd}
onDragEnd={onHandlerDragEnd}
/>
);

Expand Down
Loading

0 comments on commit a26949e

Please sign in to comment.