Rotate and move all group items correctly
All checks were successful
Build / build (push) Successful in 12s

This commit is contained in:
DrHaid
2026-01-11 18:48:09 +01:00
parent 874194923f
commit 2879da6426
2 changed files with 68 additions and 15 deletions

View File

@@ -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) =>

View File

@@ -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;
}; };