Rotate and move all group items correctly
All checks were successful
Build / build (push) Successful in 12s
All checks were successful
Build / build (push) Successful in 12s
This commit is contained in:
81
src/index.ts
81
src/index.ts
@@ -1,5 +1,5 @@
|
|||||||
import { StickyNote, Image } from "@mirohq/websdk-types";
|
import { StickyNote, Image, Group, BaseItem, GroupableItem } from "@mirohq/websdk-types";
|
||||||
import { getStickiesToChopInTree } from "./todo-tree-helper";
|
import { getStickiesToChopInTree, getTypedMiroItem } from "./todo-tree-helper";
|
||||||
|
|
||||||
export const init = async () => {
|
export const init = async () => {
|
||||||
miro.board.ui.on('icon:click', async () => {
|
miro.board.ui.on('icon:click', async () => {
|
||||||
@@ -34,30 +34,83 @@ interface AxeAnimationArgs {
|
|||||||
onChopped: () => void
|
onChopped: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RotatableItem = BaseItem & { rotation: number };
|
||||||
|
|
||||||
|
interface ItemState {
|
||||||
|
item: GroupableItem;
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
rotation: number;
|
||||||
|
deltaX: number;
|
||||||
|
deltaY: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MOVABLE_TYPES = ["card", "shape", "frame", "image", "text", "app_card", "sticky_note"];
|
||||||
|
const ROTATABLE_TYPES = ["card", "shape", "image", "text", "app_card", "sticky_note"];
|
||||||
|
|
||||||
|
const isMovable = (item: GroupableItem) => MOVABLE_TYPES.includes(item.type);
|
||||||
|
const isRotatable = (item: GroupableItem) => ROTATABLE_TYPES.includes(item.type);
|
||||||
|
|
||||||
|
const updateItemPosition = async (state: ItemState, x: number, y: number, rotation?: number) => {
|
||||||
|
if (!isMovable(state.item))
|
||||||
|
return;
|
||||||
|
|
||||||
|
(state.item as BaseItem).x = x;
|
||||||
|
(state.item as BaseItem).y = y;
|
||||||
|
if (rotation !== undefined && isRotatable(state.item)) {
|
||||||
|
(state.item as RotatableItem).rotation = rotation;
|
||||||
|
}
|
||||||
|
await state.item.sync();
|
||||||
|
};
|
||||||
|
|
||||||
const playAxeAnimation = async ({axe, stickyNote, onChopped}: AxeAnimationArgs) => {
|
const playAxeAnimation = async ({axe, stickyNote, onChopped}: AxeAnimationArgs) => {
|
||||||
const originalX = axe.x;
|
const groupItems = axe.groupId
|
||||||
const originalY = axe.y;
|
? await (await getTypedMiroItem<Group>(axe.groupId, "group"))?.getItems() ?? [axe]
|
||||||
|
: [axe];
|
||||||
|
|
||||||
|
const initialStates: ItemState[] = groupItems.map(item => ({
|
||||||
|
item,
|
||||||
|
x: (item as BaseItem).x,
|
||||||
|
y: (item as BaseItem).y,
|
||||||
|
rotation: isRotatable(item) ? (item as RotatableItem).rotation : 0,
|
||||||
|
deltaX: (item as BaseItem).x - axe.x,
|
||||||
|
deltaY: (item as BaseItem).y - axe.y
|
||||||
|
}));
|
||||||
|
|
||||||
await miro.board.bringToFront(axe);
|
await miro.board.bringToFront(axe);
|
||||||
axe.x = stickyNote.x;
|
const deltaX = stickyNote.x - axe.x;
|
||||||
axe.y = stickyNote.y;
|
const deltaY = stickyNote.y - axe.y;
|
||||||
await axe.sync();
|
|
||||||
|
|
||||||
|
// Move to target
|
||||||
|
for (const state of initialStates) {
|
||||||
|
await updateItemPosition(state, state.x + deltaX, state.y + deltaY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rotation animation
|
||||||
|
const rad = Math.PI / 2;
|
||||||
|
const cos = Math.cos(rad);
|
||||||
|
const sin = Math.sin(rad);
|
||||||
|
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
axe.rotation = 90;
|
for (const state of initialStates) {
|
||||||
await axe.sync();
|
const rotatedX = stickyNote.x + (state.deltaX * cos - state.deltaY * sin);
|
||||||
|
const rotatedY = stickyNote.y + (state.deltaX * sin + state.deltaY * cos);
|
||||||
|
await updateItemPosition(state, rotatedX, rotatedY, state.rotation + 90);
|
||||||
|
}
|
||||||
await new Promise(resolve => setTimeout(resolve, 300));
|
await new Promise(resolve => setTimeout(resolve, 300));
|
||||||
|
|
||||||
axe.rotation = 0;
|
for (const state of initialStates) {
|
||||||
await axe.sync();
|
await updateItemPosition(state, stickyNote.x + state.deltaX, stickyNote.y + state.deltaY, state.rotation);
|
||||||
|
}
|
||||||
await new Promise(resolve => setTimeout(resolve, 300));
|
await new Promise(resolve => setTimeout(resolve, 300));
|
||||||
}
|
}
|
||||||
|
|
||||||
onChopped();
|
onChopped();
|
||||||
|
|
||||||
axe.x = originalX;
|
// Move back to original position
|
||||||
axe.y = originalY;
|
for (const state of initialStates) {
|
||||||
await axe.sync();
|
await updateItemPosition(state, state.x, state.y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const postInfoNotification = async (message: string) =>
|
const postInfoNotification = async (message: string) =>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Connector, Item, StickyNote } from "@mirohq/websdk-types";
|
import { Connector, Item, StickyNote } from "@mirohq/websdk-types";
|
||||||
|
|
||||||
const getTypedMiroItem = async <T extends Item>(id: string, type: T['type']): Promise<T | undefined> => {
|
export const getTypedMiroItem = async <T extends Item>(id: string, type: T['type']): Promise<T | undefined> => {
|
||||||
const item = await miro.board.getById(id);
|
const item = await miro.board.getById(id);
|
||||||
return item?.type === type ? item as T : undefined;
|
return item?.type === type ? item as T : undefined;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user