Adds stretch

This commit is contained in:
Steve Ruiz 2021-05-27 07:32:55 +01:00
parent f0afe62073
commit e9d46a70e4
3 changed files with 65 additions and 26 deletions

View file

@ -1,10 +1,8 @@
import Command from "./command"
import history from "../history"
import { AlignType, Data, DistributeType } from "types"
import * as vec from "utils/vec"
import { Data, DistributeType } from "types"
import {
getBoundsCenter,
getBoundsFromPoints,
getCommonBounds,
getPage,
getSelectedShapes,
@ -19,17 +17,11 @@ export default function distributeCommand(data: Data, type: DistributeType) {
const entries = selectedShapes.map(
(shape) => [shape.id, getShapeUtils(shape).getBounds(shape)] as const
)
const boundsForShapes = Object.fromEntries(entries)
const commonBounds = getCommonBounds(...entries.map((entry) => entry[1]))
const innerBounds = getBoundsFromPoints(
entries.map((entry) => getBoundsCenter(entry[1]))
)
const midX = commonBounds.minX + commonBounds.width / 2
const midY = commonBounds.minY + commonBounds.height / 2
const centers = Object.fromEntries(
selectedShapes.map((shape) => [
shape.id,
@ -73,15 +65,15 @@ export default function distributeCommand(data: Data, type: DistributeType) {
])
}
} else {
const sortedByCenter = entries.sort(
const entriesToMove = entries.sort(
(a, b) => centers[a[0]][0] - centers[b[0]][0]
)
let x = commonBounds.minX
const step = (commonBounds.width - span) / (len - 1)
for (let i = 0; i < sortedByCenter.length - 1; i++) {
const [id, bounds] = sortedByCenter[i]
for (let i = 0; i < entriesToMove.length - 1; i++) {
const [id, bounds] = entriesToMove[i]
const shape = shapes[id]
getShapeUtils(shape).translateTo(shape, [x, bounds.minY])
x += bounds.width + step
@ -115,15 +107,15 @@ export default function distributeCommand(data: Data, type: DistributeType) {
])
}
} else {
const sortedByCenter = entries.sort(
const entriesToMove = entries.sort(
(a, b) => centers[a[0]][1] - centers[b[0]][1]
)
let y = commonBounds.minY
const step = (commonBounds.height - span) / (len - 1)
for (let i = 0; i < sortedByCenter.length - 1; i++) {
const [id, bounds] = sortedByCenter[i]
for (let i = 0; i < entriesToMove.length - 1; i++) {
const [id, bounds] = entriesToMove[i]
const shape = shapes[id]
getShapeUtils(shape).translateTo(shape, [bounds.minX, y])
y += bounds.height + step

View file

@ -1,36 +1,82 @@
import Command from "./command"
import history from "../history"
import { StretchType, Data } from "types"
import { getPage } from "utils/utils"
import { StretchType, Data, Edge, Corner } from "types"
import { getCommonBounds, getPage, getSelectedShapes } from "utils/utils"
import { getShapeUtils } from "lib/shape-utils"
import { current } from "immer"
export default function stretchCommand(data: Data, type: StretchType) {
const { currentPageId } = data
const initialPoints = Object.fromEntries(
Object.entries(getPage(data).shapes).map(([id, shape]) => [id, shape.point])
const initialShapes = getSelectedShapes(current(data))
const entries = initialShapes.map(
(shape) => [shape.id, getShapeUtils(shape).getBounds(shape)] as const
)
const boundsForShapes = Object.fromEntries(entries)
const commonBounds = getCommonBounds(...entries.map((entry) => entry[1]))
history.execute(
data,
new Command({
name: "distributed",
name: "stretched",
category: "canvas",
do(data) {
const { shapes } = getPage(data, currentPageId)
switch (type) {
case StretchType.Horizontal: {
for (let id in boundsForShapes) {
const initialShape = initialShapes[id]
const shape = shapes[id]
const oldBounds = boundsForShapes[id]
const newBounds = { ...oldBounds }
newBounds.minX = commonBounds.minX
newBounds.width = commonBounds.width
newBounds.maxX = commonBounds.maxX
getShapeUtils(shape).transform(shape, newBounds, {
type: Corner.TopLeft,
scaleX: newBounds.width / oldBounds.width,
scaleY: 1,
initialShape,
transformOrigin: [0.5, 0.5],
})
}
break
}
case StretchType.Vertical: {
for (let id in boundsForShapes) {
const initialShape = initialShapes[id]
const shape = shapes[id]
const oldBounds = boundsForShapes[id]
const newBounds = { ...oldBounds }
newBounds.minY = commonBounds.minY
newBounds.height = commonBounds.height
newBounds.maxY = commonBounds.maxY
getShapeUtils(shape).transform(shape, newBounds, {
type: Corner.TopLeft,
scaleX: 1,
scaleY: newBounds.height / oldBounds.height,
initialShape,
transformOrigin: [0.5, 0.5],
})
}
}
}
},
undo(data) {
const { shapes } = getPage(data, currentPageId)
for (let id in initialPoints) {
for (let id in boundsForShapes) {
const shape = shapes[id]
getShapeUtils(shape).translateTo(shape, initialPoints[id])
const initialShape = initialShapes[id]
const initialBounds = boundsForShapes[id]
getShapeUtils(shape).transform(shape, initialBounds, {
type: Corner.BottomRight,
scaleX: 1,
scaleY: 1,
initialShape,
transformOrigin: [0.5, 0.5],
})
}
},
})

View file

@ -81,8 +81,6 @@ const state = createState({
TOGGLED_STYLE_PANEL_OPEN: "toggleStylePanel",
CHANGED_STYLE: ["updateStyles", "applyStylesToSelection"],
RESET_CAMERA: "resetCamera",
ALIGNED: "alignSelection",
DISTRIBUTED: "distributeSelection",
ZOOMED_TO_FIT: "zoomCameraToFit",
ZOOMED_TO_SELECTION: {
if: "hasSelection",
@ -125,6 +123,9 @@ const state = createState({
INCREASED_CODE_FONT_SIZE: "increaseCodeFontSize",
DECREASED_CODE_FONT_SIZE: "decreaseCodeFontSize",
CHANGED_CODE_CONTROL: "updateControls",
ALIGNED: "alignSelection",
STRETCHED: "stretchSelection",
DISTRIBUTED: "distributeSelection",
MOVED: "moveSelection",
},
initial: "notPointing",