149 lines
4.6 KiB
TypeScript
149 lines
4.6 KiB
TypeScript
import { useState, useRef, useEffect } from "react";
|
|
import Konva from "konva";
|
|
import { useEditorStore, type EditorObject } from "@/pages/editor/store/editorStore";
|
|
import { useTextDefaultsStore } from "@/pages/editor/store/textDefaultsStore";
|
|
import { createDrawingObject } from "./drawingUtils";
|
|
|
|
export const useDrawingHandlers = () => {
|
|
const [isDrawing, setIsDrawing] = useState(false);
|
|
const [startPos, setStartPos] = useState({ x: 0, y: 0 });
|
|
const [tempObject, setTempObject] = useState<EditorObject | null>(null);
|
|
const transformerRef = useRef<Konva.Transformer>(null);
|
|
|
|
const { tool, addObject, updateObject, setSelectedObjectId, setSelectedObjectIds, selectedObjectIds, setTool, addTable, setSelectedTableId } = useEditorStore();
|
|
const { defaults } = useTextDefaultsStore();
|
|
|
|
useEffect(() => {
|
|
setTempObject(null);
|
|
setIsDrawing(false);
|
|
}, [tool]);
|
|
|
|
const clearSelection = () => {
|
|
setSelectedObjectIds([]);
|
|
if (transformerRef.current) {
|
|
transformerRef.current.nodes([]);
|
|
transformerRef.current.getLayer()?.batchDraw();
|
|
}
|
|
};
|
|
|
|
const handleStageMouseDown = (e: Konva.KonvaEventObject<MouseEvent>) => {
|
|
const stage = e.target.getStage();
|
|
if (!stage) return;
|
|
|
|
const clickedOnEmpty = e.target === stage;
|
|
|
|
if (clickedOnEmpty && selectedObjectIds.length > 0) {
|
|
clearSelection();
|
|
return;
|
|
}
|
|
|
|
if (tool === "select") {
|
|
if (clickedOnEmpty) {
|
|
clearSelection();
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (selectedObjectIds.length > 0) {
|
|
return;
|
|
}
|
|
|
|
const pointerPos = stage.getPointerPosition();
|
|
if (!pointerPos) return;
|
|
|
|
// تبدیل موقعیت به مختصات واقعی لایه (با در نظر گرفتن scale)
|
|
const scaleX = stage.scaleX();
|
|
const scaleY = stage.scaleY();
|
|
const realPos = {
|
|
x: pointerPos.x / scaleX,
|
|
y: pointerPos.y / scaleY,
|
|
};
|
|
|
|
setIsDrawing(true);
|
|
setStartPos(realPos);
|
|
|
|
if (tool === "text") {
|
|
const newText: EditorObject = {
|
|
id: `text-${Date.now()}`,
|
|
type: "text",
|
|
x: realPos.x,
|
|
y: realPos.y,
|
|
text: "متن جدید",
|
|
fontSize: defaults.fontSize,
|
|
lineHeight: 1.2,
|
|
textAlign: "right",
|
|
fontFamily: defaults.fontFamily,
|
|
fontWeight: defaults.fontWeight,
|
|
fill: defaults.fill,
|
|
opacity: defaults.opacity,
|
|
letterSpacing: defaults.letterSpacing,
|
|
wordSpacing: defaults.wordSpacing,
|
|
width: 150,
|
|
height: defaults.fontSize || 24,
|
|
};
|
|
addObject(newText);
|
|
setSelectedObjectId(newText.id);
|
|
setTool("select");
|
|
}
|
|
|
|
if (tool === "grid") {
|
|
addTable(realPos.x, realPos.y, 4, 5);
|
|
setSelectedTableId(null);
|
|
setTool("select");
|
|
}
|
|
};
|
|
|
|
const handleStageMouseMove = (e: Konva.KonvaEventObject<MouseEvent>) => {
|
|
if (!isDrawing || tool === "select" || tool === "text") return;
|
|
|
|
const stage = e.target.getStage();
|
|
if (!stage) return;
|
|
|
|
const pointerPos = stage.getPointerPosition();
|
|
if (!pointerPos) return;
|
|
|
|
// تبدیل موقعیت به مختصات واقعی لایه (با در نظر گرفتن scale)
|
|
const scaleX = stage.scaleX();
|
|
const scaleY = stage.scaleY();
|
|
const realPos = {
|
|
x: pointerPos.x / scaleX,
|
|
y: pointerPos.y / scaleY,
|
|
};
|
|
|
|
const newObject = createDrawingObject({ tool, startPos, pointerPos: realPos, tempObject });
|
|
if (!newObject) return;
|
|
|
|
if (!tempObject) {
|
|
addObject(newObject);
|
|
setTempObject(newObject);
|
|
} else {
|
|
const updates: Partial<EditorObject> = {
|
|
x: newObject.x,
|
|
y: newObject.y,
|
|
width: newObject.width,
|
|
height: newObject.height,
|
|
};
|
|
updateObject(tempObject.id, updates);
|
|
}
|
|
};
|
|
|
|
const handleStageMouseUp = () => {
|
|
const lastObjectId = tempObject?.id;
|
|
setIsDrawing(false);
|
|
setTempObject(null);
|
|
if (lastObjectId) {
|
|
setSelectedObjectId(lastObjectId);
|
|
setTool("select");
|
|
}
|
|
};
|
|
|
|
return {
|
|
isDrawing,
|
|
transformerRef,
|
|
handleStageMouseDown,
|
|
handleStageMouseMove,
|
|
handleStageMouseUp,
|
|
};
|
|
};
|
|
|