fix text box size

This commit is contained in:
hamid zarghami
2026-01-05 12:48:11 +03:30
parent 61d8e5a814
commit 8983301187
3 changed files with 55 additions and 70 deletions
@@ -76,6 +76,8 @@ export const useDrawingHandlers = () => {
opacity: defaults.opacity,
letterSpacing: defaults.letterSpacing,
wordSpacing: defaults.wordSpacing,
width: 150,
height: defaults.fontSize || 24,
};
addObject(newText);
setSelectedObjectId(newText.id);
+34 -66
View File
@@ -35,12 +35,9 @@ const getColorWithOpacity = (fill?: string, opacity?: number): string => {
const TextShape = ({
obj,
isSelected,
transformerRef,
onSelect,
onUpdate,
draggable,
layerRef,
}: TextShapeProps) => {
const shapeRef = useRef<Konva.Text>(null);
@@ -53,6 +50,31 @@ const TextShape = ({
}
}, []);
// Update actual text dimensions after render
useEffect(() => {
if (shapeRef.current) {
const node = shapeRef.current;
const clientRect = node.getClientRect({ skipTransform: true });
// اگر width یا height واقعی با مقدار ذخیره شده متفاوت است، آپدیت کن
if (clientRect.width && clientRect.height) {
const needsUpdate =
!obj.width ||
!obj.height ||
Math.abs((obj.width || 0) - clientRect.width) > 5 ||
Math.abs((obj.height || 0) - clientRect.height) > 5;
if (needsUpdate) {
onUpdate(obj.id, {
width: Math.ceil(clientRect.width),
height: Math.ceil(clientRect.height),
});
}
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [obj.text, obj.fontSize, obj.fontFamily, obj.fontWeight, obj.letterSpacing]);
const fontFamily = useMemo(() => getFontFamily(obj.fontFamily), [obj.fontFamily]);
const fontWeight = useMemo(() => getFontWeight(obj.fontWeight), [obj.fontWeight]);
const fillColor = useMemo(() => getColorWithOpacity(obj.fill, obj.opacity), [obj.fill, obj.opacity]);
@@ -60,6 +82,8 @@ const TextShape = ({
return (
<Text
ref={shapeRef}
id={obj.id}
name="text-object"
x={obj.x}
y={obj.y}
text={obj.text || ""}
@@ -68,8 +92,6 @@ const TextShape = ({
fontFamily={fontFamily}
fontStyle={fontWeight}
letterSpacing={obj.letterSpacing ?? 0}
width={obj.width}
height={obj.height}
align="right"
rotation={obj.rotation || 0}
draggable={draggable}
@@ -95,71 +117,17 @@ const TextShape = ({
node.scaleX(1);
node.scaleY(1);
// محاسبه اندازه واقعی متن بعد از transform
const clientRect = node.getClientRect({ skipTransform: true });
const newWidth = clientRect.width * scaleX;
const newHeight = clientRect.height * scaleY;
onUpdate(obj.id, {
x: node.x(),
y: node.y(),
rotation: node.rotation(),
width: obj.width ? Math.max(5, obj.width * scaleX) : undefined,
height: obj.height ? Math.max(5, obj.height * scaleY) : undefined,
});
}}
onDblClick={(e) => {
const textNode = e.target as Konva.Text;
const stage = textNode.getStage();
if (!stage) return;
const stageBox = stage.container().getBoundingClientRect();
const textPosition = textNode.absolutePosition();
const scaleX = stage.scaleX() || 1;
const scaleY = stage.scaleY() || 1;
const areaPosition = {
x: stageBox.left + textPosition.x * scaleX,
y: stageBox.top + textPosition.y * scaleY,
};
const textarea = document.createElement("textarea");
document.body.appendChild(textarea);
textNode.hide();
layerRef.current?.draw();
textarea.value = textNode.text();
textarea.style.position = "absolute";
textarea.style.top = `${areaPosition.y}px`;
textarea.style.left = `${areaPosition.x}px`;
textarea.style.width = `${textNode.width() * scaleX}px`;
textarea.style.fontSize = `${textNode.fontSize() * scaleY}px`;
textarea.style.border = "none";
textarea.style.padding = "0px";
textarea.style.margin = "0px";
textarea.style.overflow = "hidden";
textarea.style.background = "transparent";
textarea.style.outline = "none";
textarea.style.resize = "none";
textarea.style.fontFamily = fontFamily;
textarea.style.fontWeight = fontWeight === "bold" ? "bold" : "normal";
textarea.style.letterSpacing = `${obj.letterSpacing ?? 0}px`;
textarea.style.textAlign = textNode.align() || "right";
textarea.style.direction = "rtl";
textarea.focus();
const removeTextarea = () => {
document.body.removeChild(textarea);
textNode.show();
textNode.text(textarea.value);
onUpdate(obj.id, { text: textarea.value });
layerRef.current?.draw();
};
textarea.addEventListener("keydown", (e) => {
if (e.key === "Enter" && !e.shiftKey) {
removeTextarea();
}
if (e.key === "Escape") {
removeTextarea();
}
});
textarea.addEventListener("blur", () => {
removeTextarea();
width: Math.max(5, newWidth),
height: Math.max(5, newHeight),
});
}}
/>
+19 -4
View File
@@ -696,10 +696,25 @@ export const useEditorStore = create<EditorStoreType>((set, get) => {
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;
// برای متن‌هایی که width و height ندارند، از مقادیر پیش‌فرض استفاده کن
let w = obj.width || 0;
let h = obj.height || 0;
if (obj.type === "text") {
// اگر متن width نداره، از fontSize و طول متن برای تخمین استفاده کن
if (!w) {
const textLength = (obj.text || "").length;
const fontSize = obj.fontSize || 24;
w = Math.max(textLength * fontSize * 0.6, 50);
}
// اگر height نداره، از fontSize استفاده کن
if (!h) {
h = obj.fontSize || 24;
}
}
const cx = (obj.x || 0) + w / 2;
const cy = (obj.y || 0) + h / 2;
const rot = ((obj.rotation || 0) * Math.PI) / 180;
// محاسبه چهار گوشه rectangle با rotation