Skip to content

Commit

Permalink
Add rotate!
Browse files Browse the repository at this point in the history
  • Loading branch information
aboodman committed Mar 10, 2021
1 parent 5219fac commit bd5cb44
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 9 deletions.
8 changes: 8 additions & 0 deletions frontend/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
putShape,
moveShape,
resizeShape,
rotateShape,
deleteShape,
} from "../shared/shape";
import {
Expand Down Expand Up @@ -76,6 +77,13 @@ export function createData(rep: Replicache) {
}
),

rotateShape: rep.register(
"rotateShape",
async (tx: WriteTransaction, args: { id: string; ddeg: number }) => {
await rotateShape(writeStorage(tx), args);
}
),

initClientState: rep.register(
"initClientState",
async (
Expand Down
1 change: 1 addition & 0 deletions frontend/designer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export function Designer({ data }: { data: Data }) {
data,
id: selectedID,
highlight: true,
containerOffsetTop: ref.current && ref.current.offsetTop,
}}
/>
)
Expand Down
71 changes: 62 additions & 9 deletions frontend/selection.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
import { Data } from "./data";
import type { Shape } from "../shared/shape";
import { DragEvent, useDrag } from "./drag";
import { Rect } from "./rect";

export function Selection({ data, id }: { data: Data; id: string }) {
export function Selection({
data,
id,
containerOffsetTop,
}: {
data: Data;
id: string;
containerOffsetTop: number | null;
}) {
const shape = data.useShapeByID(id);
const gripSize = 19;

const onDrag = (e: DragEvent) => {
const center = (shape: Shape) => {
return {
x: shape.x + shape.width / 2,
y: shape.y + shape.height / 2,
};
};

const onResize = (e: DragEvent) => {
if (!shape) {
return;
}

const shapeCenter = {
x: shape.x + shape.width / 2,
y: shape.y + shape.height / 2,
};
const shapeCenter = center(shape);

const size = (x1: number, x2: number, y1: number, y2: number) => {
const distanceSqFromCenterToCursor =
Expand All @@ -33,7 +46,25 @@ export function Selection({ data, id }: { data: Data; id: string }) {
data.resizeShape({ id, ds: s1 - s0 });
};

const drag = useDrag({ onDrag });
const onRotate = (e: DragEvent) => {
if (!shape || containerOffsetTop === null) {
return;
}

const offsetY = e.pageY - containerOffsetTop;

const shapeCenter = center(shape);
const before = Math.atan2(
offsetY - e.movementY - shapeCenter.y,
e.pageX - e.movementX - shapeCenter.x
);
const after = Math.atan2(offsetY - shapeCenter.y, e.pageX - shapeCenter.x);

data.rotateShape({ id, ddeg: ((after - before) * 180) / Math.PI });
};

const resizer = useDrag({ onDrag: onResize });
const rotator = useDrag({ onDrag: onRotate });

if (!shape) {
return null;
Expand All @@ -56,7 +87,6 @@ export function Selection({ data, id }: { data: Data; id: string }) {
height: shape.height,
pointerEvents: "none",
}}
{...drag}
>
<svg
width={gripSize}
Expand All @@ -68,8 +98,8 @@ export function Selection({ data, id }: { data: Data; id: string }) {
}px, 0)`,
cursor: "grab",
pointerEvents: "all",
...drag,
}}
{...resizer}
>
<rect
strokeWidth={2}
Expand All @@ -79,6 +109,29 @@ export function Selection({ data, id }: { data: Data; id: string }) {
fill="white"
/>
</svg>
<svg
width={gripSize}
height={gripSize}
style={{
position: "absolute",
transform: `translate3d(${shape.width + gripSize * 1.5}px, ${
shape.height / 2 - gripSize / 2
}px, 0)`,
cursor: "grab",
pointerEvents: "all",
}}
{...rotator}
>
<ellipse
cx={gripSize / 2}
cy={gripSize / 2}
rx={gripSize / 2 - 1}
ry={gripSize / 2 - 1}
strokeWidth={2}
stroke="rgb(74,158,255)"
fill="white"
/>
</svg>
</div>
</div>
);
Expand Down
12 changes: 12 additions & 0 deletions pages/api/replicache-push.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
putShape,
moveShape,
resizeShape,
rotateShape,
shape,
deleteShape,
} from "../../shared/shape";
Expand Down Expand Up @@ -57,6 +58,14 @@ const mutation = t.union([
ds: t.number,
}),
}),
t.type({
id: t.number,
name: t.literal("rotateShape"),
args: t.type({
id: t.string,
ddeg: t.number,
}),
}),
t.type({
id: t.number,
name: t.literal("initClientState"),
Expand Down Expand Up @@ -172,6 +181,9 @@ export default async (req: NextApiRequest, res: NextApiResponse) => {
case "resizeShape":
await resizeShape(s, mutation.args);
break;
case "rotateShape":
await rotateShape(s, mutation.args);
break;
case "initClientState":
await initClientState(s, mutation.args);
break;
Expand Down
11 changes: 11 additions & 0 deletions shared/shape.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,17 @@ export async function resizeShape(
}
}

export async function rotateShape(
storage: WriteStorage,
{ id, ddeg }: { id: string; ddeg: number }
): Promise<void> {
const shape = await getShape(storage, id);
if (shape) {
shape.rotate += ddeg;
await putShape(storage, { id, shape });
}
}

function key(id: string): string {
return `shape-${id}`;
}

0 comments on commit bd5cb44

Please sign in to comment.