Transforming rotated items

This commit is contained in:
Steve Ruiz 2021-05-18 11:45:29 +01:00
parent 1ece606db0
commit da8f812090
5 changed files with 91 additions and 14 deletions

View file

@ -73,6 +73,8 @@ const ellipse = createShape<EllipseShape>({
}, },
hitTestBounds(this, shape, brushBounds) { hitTestBounds(this, shape, brushBounds) {
// TODO: Account for rotation
const shapeBounds = this.getBounds(shape) const shapeBounds = this.getBounds(shape)
return ( return (

View file

@ -61,11 +61,13 @@ export interface ShapeUtility<K extends Shape> {
bounds: Bounds, bounds: Bounds,
info: { info: {
type: TransformEdge | TransformCorner type: TransformEdge | TransformCorner
boundsRotation: number
initialShape: K initialShape: K
initialShapeBounds: BoundsSnapshot initialShapeBounds: BoundsSnapshot
initialBounds: Bounds initialBounds: Bounds
isFlippedX: boolean isFlippedX: boolean
isFlippedY: boolean isFlippedY: boolean
isSingle: boolean
anchor: TransformEdge | TransformCorner anchor: TransformEdge | TransformCorner
} }
): K ): K

View file

@ -103,9 +103,44 @@ const rectangle = createShape<RectangleShape>({
return shape return shape
}, },
transform(shape, bounds) { transform(
shape.point = [bounds.minX, bounds.minY] shape,
shape.size = [bounds.width, bounds.height] shapeBounds,
{ initialShape, isSingle, initialShapeBounds, isFlippedX, isFlippedY }
) {
// TODO: Apply rotation to single-selection items
if (shape.rotation === 0 || isSingle) {
shape.size = [shapeBounds.width, shapeBounds.height]
shape.point = [shapeBounds.minX, shapeBounds.minY]
} else {
shape.size = vec.mul(
initialShape.size,
Math.min(
shapeBounds.width / initialShapeBounds.width,
shapeBounds.height / initialShapeBounds.height
)
)
const newCenter = [
shapeBounds.minX + shapeBounds.width / 2,
shapeBounds.minY + shapeBounds.height / 2,
]
shape.point = vec.sub(newCenter, vec.div(shape.size, 2))
}
// Rotation for flipped shapes
shape.rotation = initialShape.rotation
if (isFlippedX) {
shape.rotation *= -1
}
if (isFlippedY) {
shape.rotation *= -1
}
return shape return shape
}, },

View file

@ -22,6 +22,8 @@ export default function translateCommand(
initialBounds, initialBounds,
currentPageId, currentPageId,
selectedIds, selectedIds,
isSingle,
boundsRotation,
} = after } = after
const { shapes } = data.document.pages[currentPageId] const { shapes } = data.document.pages[currentPageId]
@ -35,8 +37,10 @@ export default function translateCommand(
initialShape, initialShape,
initialShapeBounds, initialShapeBounds,
initialBounds, initialBounds,
boundsRotation,
isFlippedX: false, isFlippedX: false,
isFlippedY: false, isFlippedY: false,
isSingle,
anchor, anchor,
}) })
}) })
@ -48,6 +52,8 @@ export default function translateCommand(
initialBounds, initialBounds,
currentPageId, currentPageId,
selectedIds, selectedIds,
isSingle,
boundsRotation,
} = before } = before
const { shapes } = data.document.pages[currentPageId] const { shapes } = data.document.pages[currentPageId]
@ -61,8 +67,10 @@ export default function translateCommand(
initialShape, initialShape,
initialShapeBounds, initialShapeBounds,
initialBounds, initialBounds,
boundsRotation,
isFlippedX: false, isFlippedX: false,
isFlippedY: false, isFlippedY: false,
isSingle,
anchor: type, anchor: type,
}) })
}) })

View file

@ -32,6 +32,18 @@ export default class TransformSession extends BaseSession {
super(data) super(data)
this.origin = point this.origin = point
this.transformType = transformType this.transformType = transformType
// if (data.selectedIds.size === 1) {
// const shape =
// data.document.pages[data.currentPageId].shapes[
// Array.from(data.selectedIds.values())[0]
// ]
// if (shape.rotation > 0) {
// }
// }
this.snapshot = getTransformSnapshot(data, transformType) this.snapshot = getTransformSnapshot(data, transformType)
const { minX, minY, maxX, maxY } = this.snapshot.initialBounds const { minX, minY, maxX, maxY } = this.snapshot.initialBounds
@ -43,21 +55,26 @@ export default class TransformSession extends BaseSession {
} }
update(data: Data, point: number[]) { update(data: Data, point: number[]) {
const { shapeBounds, initialBounds, currentPageId, selectedIds } =
this.snapshot
const { shapes } = data.document.pages[currentPageId]
const delta = vec.vec(this.origin, point)
const { const {
corners: { a, b }, corners: { a, b },
transformType, transformType,
} = this } = this
// Edge Transform const {
boundsRotation,
shapeBounds,
initialBounds,
currentPageId,
selectedIds,
isSingle,
} = this.snapshot
const { shapes } = data.document.pages[currentPageId]
const delta = vec.vec(this.origin, point)
/* /*
Edge transform Transforms
Corners a and b are the original top-left and bottom-right corners of the Corners a and b are the original top-left and bottom-right corners of the
bounding box. Depending on what the user is dragging, change one or both bounding box. Depending on what the user is dragging, change one or both
@ -153,8 +170,10 @@ export default class TransformSession extends BaseSession {
initialShape, initialShape,
initialShapeBounds, initialShapeBounds,
initialBounds, initialBounds,
boundsRotation,
isFlippedX: this.isFlippedX, isFlippedX: this.isFlippedX,
isFlippedY: this.isFlippedY, isFlippedY: this.isFlippedY,
isSingle,
anchor: getTransformAnchor( anchor: getTransformAnchor(
this.transformType, this.transformType,
this.isFlippedX, this.isFlippedX,
@ -165,8 +184,14 @@ export default class TransformSession extends BaseSession {
} }
cancel(data: Data) { cancel(data: Data) {
const { shapeBounds, initialBounds, currentPageId, selectedIds } = const {
this.snapshot shapeBounds,
boundsRotation,
initialBounds,
currentPageId,
selectedIds,
isSingle,
} = this.snapshot
const { shapes } = data.document.pages[currentPageId] const { shapes } = data.document.pages[currentPageId]
@ -180,8 +205,10 @@ export default class TransformSession extends BaseSession {
initialShape, initialShape,
initialShapeBounds, initialShapeBounds,
initialBounds, initialBounds,
boundsRotation,
isFlippedX: false, isFlippedX: false,
isFlippedY: false, isFlippedY: false,
isSingle,
anchor: getTransformAnchor(this.transformType, false, false), anchor: getTransformAnchor(this.transformType, false, false),
}) })
}) })
@ -205,6 +232,7 @@ export function getTransformSnapshot(
document: { pages }, document: { pages },
selectedIds, selectedIds,
currentPageId, currentPageId,
boundsRotation,
} = current(data) } = current(data)
const pageShapes = pages[currentPageId].shapes const pageShapes = pages[currentPageId].shapes
@ -226,6 +254,8 @@ export function getTransformSnapshot(
currentPageId, currentPageId,
type: transformType, type: transformType,
initialBounds: bounds, initialBounds: bounds,
boundsRotation,
isSingle: selectedIds.size === 1,
selectedIds: new Set(selectedIds), selectedIds: new Set(selectedIds),
shapeBounds: Object.fromEntries( shapeBounds: Object.fromEntries(
Array.from(selectedIds.values()).map((id) => { Array.from(selectedIds.values()).map((id) => {