Fix rotation transforms

This commit is contained in:
Jason Miller
2020-12-14 17:32:29 -05:00
parent 588ec61543
commit c459319b21
2 changed files with 62 additions and 23 deletions

View File

@@ -109,14 +109,16 @@ export default class Transform extends Component<Props, State> {
this.setState(this.fromPreprocessorState(preprocessorState)); this.setState(this.fromPreprocessorState(preprocessorState));
} }
const { width, height } = source.decoded; const { width, height } = source.decoded;
const cropWidth = width - crop.left - crop.right; if (crop) {
const cropHeight = height - crop.top - crop.bottom; const cropWidth = width - crop.left - crop.right;
for (const [id, preset] of Object.entries(cropPresets)) { const cropHeight = height - crop.top - crop.bottom;
if (cropHeight * preset.ratio === cropWidth) { for (const [id, preset] of Object.entries(cropPresets)) {
if (cropPreset !== id) { if (cropHeight * preset.ratio === cropWidth) {
this.setState({ cropPreset: id as CropPresetId }); if (cropPreset !== id) {
this.setState({ cropPreset: id as CropPresetId });
}
break;
} }
break;
} }
} }
} }
@@ -268,12 +270,28 @@ export default class Transform extends Component<Props, State> {
this.setState({ crop }); this.setState({ crop });
} }
// yeah these could just += 90 private adjustOffsetAfterRotation = (wideToTall: boolean) => {
const image = this.props.source.decoded;
let { x, y } = this.pinchZoom.current!;
let { width, height } = image;
if (wideToTall) {
[width, height] = [height, width];
}
x += (width - height) / 2;
y += (height - width) / 2;
this.pinchZoom.current!.setTransform({ x, y });
};
private rotateClockwise = () => { private rotateClockwise = () => {
let { rotate, crop } = this.state; let { rotate, crop } = this.state;
this.setState({ this.setState(
rotate: ((rotate + 90) % 360) as typeof ROTATE_ORIENTATIONS[number], {
}); rotate: ((rotate + 90) % 360) as typeof ROTATE_ORIENTATIONS[number],
},
() => {
this.adjustOffsetAfterRotation(rotate === 0 || rotate === 180);
},
);
this.setCrop({ this.setCrop({
top: crop.left, top: crop.left,
left: crop.bottom, left: crop.bottom,
@@ -284,11 +302,16 @@ export default class Transform extends Component<Props, State> {
private rotateCounterClockwise = () => { private rotateCounterClockwise = () => {
let { rotate, crop } = this.state; let { rotate, crop } = this.state;
this.setState({ this.setState(
rotate: (rotate {
? rotate - 90 rotate: (rotate
: 270) as typeof ROTATE_ORIENTATIONS[number], ? rotate - 90
}); : 270) as typeof ROTATE_ORIENTATIONS[number],
},
() => {
this.adjustOffsetAfterRotation(rotate === 0 || rotate === 180);
},
);
this.setCrop({ this.setCrop({
top: crop.right, top: crop.right,
right: crop.bottom, right: crop.bottom,
@@ -348,11 +371,16 @@ export default class Transform extends Component<Props, State> {
{ scale, editingScale, rotate, flip, crop, cropPreset, lockAspect }: State, { scale, editingScale, rotate, flip, crop, cropPreset, lockAspect }: State,
) { ) {
const image = source.decoded; const image = source.decoded;
const rotated = rotate === 90 || rotate === 270;
const width = source.decoded.width - crop.left - crop.right; const displayWidth = rotated ? image.height : image.width;
const height = source.decoded.height - crop.top - crop.bottom; const displayHeight = rotated ? image.width : image.height;
const width = displayWidth - crop.left - crop.right;
const height = displayHeight - crop.top - crop.bottom;
let transform = let transform =
`translate(-50%, -50%) ` +
`rotate(${rotate}deg) ` + `rotate(${rotate}deg) ` +
`scale(${flip.horizontal ? -1 : 1}, ${flip.vertical ? -1 : 1})`; `scale(${flip.horizontal ? -1 : 1}, ${flip.vertical ? -1 : 1})`;
@@ -367,12 +395,12 @@ export default class Transform extends Component<Props, State> {
onChange={this.onPinchZoomChange} onChange={this.onPinchZoomChange}
ref={this.pinchZoom} ref={this.pinchZoom}
> >
{/* <Backdrop width={image.width} height={image.height} /> */} {/* <Backdrop width={displayWidth} height={displayHeight} /> */}
<div <div
class={style.wrap} class={style.wrap}
style={{ style={{
width: image.width, width: displayWidth,
height: image.height, height: displayHeight,
}} }}
> >
<CanvasImage <CanvasImage
@@ -382,7 +410,7 @@ export default class Transform extends Component<Props, State> {
/> />
{crop && ( {crop && (
<Cropper <Cropper
size={{ width: image.width, height: image.height }} size={{ width: displayWidth, height: displayHeight }}
scale={scale} scale={scale}
lockAspect={lockAspect} lockAspect={lockAspect}
crop={crop} crop={crop}

View File

@@ -3,8 +3,14 @@
} }
.wrap { .wrap {
position: absolute;
left: 50%;
top: 50%;
/** can't use transform-origin here, pinch-zoom relies on 0,0 */
transform: translate(-50%, -50%) translate(var(--x), var(--y))
scale(var(--scale));
overflow: visible; overflow: visible;
contain: size layout; contain: layout;
will-change: initial !important; will-change: initial !important;
} }
@@ -42,6 +48,11 @@
will-change: auto; will-change: auto;
/* Prevent the image becoming misshapen due to default flexbox layout. */ /* Prevent the image becoming misshapen due to default flexbox layout. */
flex-shrink: 0; flex-shrink: 0;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
transform-origin: 50% 50%;
} }
.cancel, .cancel,