base group
This commit is contained in:
@@ -13,7 +13,8 @@ export type ToolType =
|
||||
| "document"
|
||||
| "video"
|
||||
| "link"
|
||||
| "grid";
|
||||
| "grid"
|
||||
| "group";
|
||||
|
||||
export type TableCell = {
|
||||
id: string;
|
||||
@@ -83,6 +84,10 @@ type EditorStoreType = {
|
||||
duplicateObject: (id: string) => void;
|
||||
selectedObjectId: string | null;
|
||||
setSelectedObjectId: (id: string | null) => void;
|
||||
selectedObjectIds: string[];
|
||||
setSelectedObjectIds: (ids: string[]) => void;
|
||||
addToSelection: (id: string) => void;
|
||||
removeFromSelection: (id: string) => void;
|
||||
selectedTableId: string | null;
|
||||
setSelectedTableId: (id: string | null) => void;
|
||||
selectedCellId: string | null;
|
||||
@@ -301,7 +306,37 @@ export const useEditorStore = create<EditorStoreType>((set, get) => {
|
||||
}));
|
||||
},
|
||||
selectedObjectId: null,
|
||||
setSelectedObjectId: (id) => set({ selectedObjectId: id }),
|
||||
setSelectedObjectId: (id) => {
|
||||
set({
|
||||
selectedObjectId: id,
|
||||
selectedObjectIds: id ? [id] : []
|
||||
});
|
||||
},
|
||||
selectedObjectIds: [],
|
||||
setSelectedObjectIds: (ids) => {
|
||||
set({
|
||||
selectedObjectIds: ids,
|
||||
selectedObjectId: ids.length > 0 ? ids[0] : null
|
||||
});
|
||||
},
|
||||
addToSelection: (id) => {
|
||||
const state = get();
|
||||
if (!state.selectedObjectIds.includes(id)) {
|
||||
const newIds = [...state.selectedObjectIds, id];
|
||||
set({
|
||||
selectedObjectIds: newIds,
|
||||
selectedObjectId: newIds[0]
|
||||
});
|
||||
}
|
||||
},
|
||||
removeFromSelection: (id) => {
|
||||
const state = get();
|
||||
const newIds = state.selectedObjectIds.filter(selectedId => selectedId !== id);
|
||||
set({
|
||||
selectedObjectIds: newIds,
|
||||
selectedObjectId: newIds.length > 0 ? newIds[0] : null
|
||||
});
|
||||
},
|
||||
selectedTableId: null,
|
||||
setSelectedTableId: (id) => set({ selectedTableId: id }),
|
||||
selectedCellId: null,
|
||||
@@ -650,6 +685,57 @@ export const useEditorStore = create<EditorStoreType>((set, get) => {
|
||||
if (objectIds.length < 2) return;
|
||||
|
||||
const groupId = `group-${crypto.randomUUID()}`;
|
||||
const objectsToGroup = state.objects.filter((obj) => objectIds.includes(obj.id));
|
||||
|
||||
if (objectsToGroup.length === 0) return;
|
||||
|
||||
// محاسبه bounds گروه با در نظر گرفتن rotation
|
||||
let minX = Infinity;
|
||||
let minY = Infinity;
|
||||
let maxX = -Infinity;
|
||||
let maxY = -Infinity;
|
||||
|
||||
objectsToGroup.forEach((obj) => {
|
||||
const cx = (obj.x || 0) + (obj.width || 0) / 2;
|
||||
const cy = (obj.y || 0) + (obj.height || 0) / 2;
|
||||
const w = obj.width || 0;
|
||||
const h = obj.height || 0;
|
||||
const rot = ((obj.rotation || 0) * Math.PI) / 180;
|
||||
|
||||
// محاسبه چهار گوشه rectangle با rotation
|
||||
const corners = [
|
||||
{ x: -w / 2, y: -h / 2 },
|
||||
{ x: w / 2, y: -h / 2 },
|
||||
{ x: w / 2, y: h / 2 },
|
||||
{ x: -w / 2, y: h / 2 },
|
||||
];
|
||||
|
||||
corners.forEach((corner) => {
|
||||
const rotatedX = corner.x * Math.cos(rot) - corner.y * Math.sin(rot);
|
||||
const rotatedY = corner.x * Math.sin(rot) + corner.y * Math.cos(rot);
|
||||
const finalX = cx + rotatedX;
|
||||
const finalY = cy + rotatedY;
|
||||
minX = Math.min(minX, finalX);
|
||||
minY = Math.min(minY, finalY);
|
||||
maxX = Math.max(maxX, finalX);
|
||||
maxY = Math.max(maxY, finalY);
|
||||
});
|
||||
});
|
||||
|
||||
const groupWidth = maxX - minX;
|
||||
const groupHeight = maxY - minY;
|
||||
|
||||
// ایجاد group object
|
||||
const groupObject: EditorObject = {
|
||||
id: groupId,
|
||||
type: "group",
|
||||
x: minX,
|
||||
y: minY,
|
||||
width: groupWidth,
|
||||
height: groupHeight,
|
||||
};
|
||||
|
||||
// اضافه کردن groupId به objectهای داخل گروه
|
||||
const updateObjects = (objects: EditorObject[]) =>
|
||||
objects.map((obj) =>
|
||||
objectIds.includes(obj.id) ? { ...obj, groupId } : obj
|
||||
@@ -657,25 +743,32 @@ export const useEditorStore = create<EditorStoreType>((set, get) => {
|
||||
|
||||
if (state.currentPageId) {
|
||||
set((state) => ({
|
||||
objects: updateObjects(state.objects),
|
||||
objects: [...updateObjects(state.objects), groupObject],
|
||||
pages: state.pages.map((p) =>
|
||||
p.id === state.currentPageId
|
||||
? { ...p, objects: updateObjects(p.objects) }
|
||||
? { ...p, objects: [...updateObjects(p.objects), groupObject] }
|
||||
: p
|
||||
),
|
||||
selectedObjectId: groupId,
|
||||
selectedObjectIds: [groupId],
|
||||
}));
|
||||
return;
|
||||
}
|
||||
set((state) => ({
|
||||
objects: updateObjects(state.objects),
|
||||
objects: [...updateObjects(state.objects), groupObject],
|
||||
selectedObjectId: groupId,
|
||||
selectedObjectIds: [groupId],
|
||||
}));
|
||||
},
|
||||
ungroupObjects: (groupId) => {
|
||||
const state = get();
|
||||
// حذف groupId از objectهای داخل گروه و حذف group object
|
||||
const updateObjects = (objects: EditorObject[]) =>
|
||||
objects.map((obj) =>
|
||||
obj.groupId === groupId ? { ...obj, groupId: undefined } : obj
|
||||
);
|
||||
objects
|
||||
.map((obj) =>
|
||||
obj.groupId === groupId ? { ...obj, groupId: undefined } : obj
|
||||
)
|
||||
.filter((obj) => obj.id !== groupId); // حذف group object
|
||||
|
||||
if (state.currentPageId) {
|
||||
set((state) => ({
|
||||
@@ -685,12 +778,20 @@ export const useEditorStore = create<EditorStoreType>((set, get) => {
|
||||
? { ...p, objects: updateObjects(p.objects) }
|
||||
: p
|
||||
),
|
||||
selectedObjectId: null,
|
||||
selectedObjectIds: [],
|
||||
}));
|
||||
return;
|
||||
}
|
||||
set((state) => ({
|
||||
objects: updateObjects(state.objects),
|
||||
selectedObjectId: null,
|
||||
selectedObjectIds: [],
|
||||
}));
|
||||
},
|
||||
getGroupObjects: (groupId) => {
|
||||
const state = get();
|
||||
return state.objects.filter((obj) => obj.groupId === groupId);
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user