can edit text + fix font weight - remove character space
This commit is contained in:
@@ -28,7 +28,7 @@ const AbstractShape = ({ obj, isSelected, transformerRef, onSelect, onUpdate, dr
|
||||
outerRadius={radius}
|
||||
fill={obj.fill}
|
||||
stroke={isSelected ? "#3b82f6" : obj.stroke}
|
||||
strokeWidth={isSelected ? 3 : obj.strokeWidth || 2}
|
||||
strokeWidth={isSelected ? 3 : (obj.strokeWidth ?? 0)}
|
||||
rotation={obj.rotation || 0}
|
||||
draggable={draggable}
|
||||
onClick={() => {
|
||||
|
||||
@@ -20,7 +20,7 @@ const ArrowShape = ({ obj, isSelected, transformerRef, onSelect, onUpdate, dragg
|
||||
y={obj.y}
|
||||
points={[0, 0, (obj.width || 0) - obj.x, (obj.height || 0) - obj.y]}
|
||||
stroke={isSelected ? "#3b82f6" : obj.stroke || "#000000"}
|
||||
strokeWidth={isSelected ? 3 : obj.strokeWidth || 2}
|
||||
strokeWidth={isSelected ? 3 : (obj.strokeWidth ?? 0)}
|
||||
fill={isSelected ? "#3b82f6" : obj.stroke || "#000000"}
|
||||
rotation={obj.rotation || 0}
|
||||
draggable={draggable}
|
||||
|
||||
@@ -21,7 +21,7 @@ const CircleShape = ({ obj, isSelected, transformerRef, onSelect, onUpdate, drag
|
||||
radius={(obj.width || 50) / 2}
|
||||
fill={obj.fill}
|
||||
stroke={isSelected ? "#3b82f6" : obj.stroke}
|
||||
strokeWidth={isSelected ? 3 : obj.strokeWidth || 2}
|
||||
strokeWidth={isSelected ? 3 : (obj.strokeWidth ?? 0)}
|
||||
rotation={obj.rotation || 0}
|
||||
draggable={draggable}
|
||||
onClick={() => {
|
||||
|
||||
@@ -20,7 +20,7 @@ const LineShape = ({ obj, isSelected, transformerRef, onSelect, onUpdate, dragga
|
||||
y={obj.y}
|
||||
points={[0, 0, (obj.width || 0) - obj.x, (obj.height || 0) - obj.y]}
|
||||
stroke={isSelected ? "#3b82f6" : obj.stroke || "#000000"}
|
||||
strokeWidth={isSelected ? 3 : obj.strokeWidth || 2}
|
||||
strokeWidth={isSelected ? 3 : (obj.strokeWidth ?? 0)}
|
||||
rotation={obj.rotation || 0}
|
||||
draggable={draggable}
|
||||
onClick={() => {
|
||||
|
||||
@@ -22,7 +22,7 @@ const RectangleShape = ({ obj, isSelected, transformerRef, onSelect, onUpdate, d
|
||||
height={obj.height || 100}
|
||||
fill={obj.fill}
|
||||
stroke={isSelected ? "#3b82f6" : obj.stroke}
|
||||
strokeWidth={isSelected ? 3 : obj.strokeWidth || 2}
|
||||
strokeWidth={isSelected ? 3 : (obj.strokeWidth ?? 0)}
|
||||
rotation={obj.rotation || 0}
|
||||
draggable={draggable}
|
||||
onClick={() => {
|
||||
|
||||
@@ -4,33 +4,33 @@ import Konva from "konva";
|
||||
import type { TextShapeProps } from "./types";
|
||||
|
||||
const getFontFamily = (fontFamily?: string): string => {
|
||||
const fontMap: Record<string, string> = {
|
||||
"1": "irancell",
|
||||
"2": "irancell",
|
||||
};
|
||||
return fontMap[fontFamily || "1"] || "irancell";
|
||||
const fontMap: Record<string, string> = {
|
||||
"1": "irancell",
|
||||
"2": "irancell",
|
||||
};
|
||||
return fontMap[fontFamily || "1"] || "irancell";
|
||||
};
|
||||
|
||||
const getFontWeight = (fontWeight?: string): string | number => {
|
||||
const weightMap: Record<string, string | number> = {
|
||||
bold: "600",
|
||||
normal: "300",
|
||||
"300": "300",
|
||||
};
|
||||
return weightMap[fontWeight || "normal"] || "300";
|
||||
const getFontWeight = (fontWeight?: string): string => {
|
||||
const weightMap: Record<string, string> = {
|
||||
bold: "bold",
|
||||
normal: "normal",
|
||||
"300": "300",
|
||||
};
|
||||
return weightMap[fontWeight || "normal"] || "normal";
|
||||
};
|
||||
|
||||
const getColorWithOpacity = (fill?: string, opacity?: number): string => {
|
||||
if (!fill) return "#000000";
|
||||
if (opacity === undefined || opacity === 100) return fill;
|
||||
if (!fill) return "#000000";
|
||||
if (opacity === undefined || opacity === 100) return fill;
|
||||
|
||||
const hex = fill.replace("#", "");
|
||||
const r = parseInt(hex.substring(0, 2), 16);
|
||||
const g = parseInt(hex.substring(2, 4), 16);
|
||||
const b = parseInt(hex.substring(4, 6), 16);
|
||||
const alpha = opacity / 100;
|
||||
const hex = fill.replace("#", "");
|
||||
const r = parseInt(hex.substring(0, 2), 16);
|
||||
const g = parseInt(hex.substring(2, 4), 16);
|
||||
const b = parseInt(hex.substring(4, 6), 16);
|
||||
const alpha = opacity / 100;
|
||||
|
||||
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
||||
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
||||
};
|
||||
|
||||
const TextShape = ({
|
||||
@@ -46,10 +46,23 @@ const TextShape = ({
|
||||
|
||||
useEffect(() => {
|
||||
if (isSelected && shapeRef.current && transformerRef.current) {
|
||||
transformerRef.current.nodes([shapeRef.current]);
|
||||
transformerRef.current.getLayer()?.batchDraw();
|
||||
const textNode = shapeRef.current;
|
||||
|
||||
// تنظیم offset برای حذف فضای خالی
|
||||
textNode.offsetX(0);
|
||||
textNode.offsetY(0);
|
||||
|
||||
transformerRef.current.nodes([textNode]);
|
||||
|
||||
// بهروزرسانی transformer بعد از یک تیک برای محاسبه دقیق bounds
|
||||
setTimeout(() => {
|
||||
if (transformerRef.current && shapeRef.current) {
|
||||
transformerRef.current.forceUpdate();
|
||||
transformerRef.current.getLayer()?.batchDraw();
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
}, [isSelected, transformerRef]);
|
||||
}, [isSelected, transformerRef, obj.text, obj.width, obj.height, obj.fontSize, obj.fontFamily, obj.fontWeight]);
|
||||
|
||||
const fontFamily = useMemo(() => getFontFamily(obj.fontFamily), [obj.fontFamily]);
|
||||
const fontWeight = useMemo(() => getFontWeight(obj.fontWeight), [obj.fontWeight]);
|
||||
@@ -64,10 +77,11 @@ const TextShape = ({
|
||||
fontSize={obj.fontSize || 24}
|
||||
fill={fillColor}
|
||||
fontFamily={fontFamily}
|
||||
fontWeight={fontWeight}
|
||||
letterSpacing={obj.letterSpacing}
|
||||
fontStyle={fontWeight}
|
||||
letterSpacing={obj.letterSpacing ?? 0}
|
||||
width={obj.width}
|
||||
height={obj.height}
|
||||
align="right"
|
||||
rotation={obj.rotation || 0}
|
||||
draggable={draggable}
|
||||
onClick={() => {
|
||||
@@ -105,35 +119,42 @@ const TextShape = ({
|
||||
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: stage.container().offsetLeft + textPosition.x,
|
||||
y: stage.container().offsetTop + textPosition.y,
|
||||
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()}px`;
|
||||
textarea.style.fontSize = `${textNode.fontSize()}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.padding = "50px";
|
||||
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 = String(fontWeight);
|
||||
textarea.style.letterSpacing = `${obj.letterSpacing || 0}px`;
|
||||
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();
|
||||
|
||||
@@ -24,7 +24,7 @@ const TriangleShape = ({ obj, isSelected, transformerRef, onSelect, onUpdate, dr
|
||||
radius={radius}
|
||||
fill={obj.fill}
|
||||
stroke={isSelected ? "#3b82f6" : obj.stroke}
|
||||
strokeWidth={isSelected ? 3 : obj.strokeWidth || 2}
|
||||
strokeWidth={isSelected ? 3 : (obj.strokeWidth ?? 0)}
|
||||
rotation={obj.rotation || 0}
|
||||
draggable={draggable}
|
||||
onClick={() => {
|
||||
|
||||
@@ -30,7 +30,7 @@ const VideoShape = ({
|
||||
height={obj.height || 300}
|
||||
fill="#000000"
|
||||
stroke={isSelected ? "#3b82f6" : "#666666"}
|
||||
strokeWidth={isSelected ? 3 : 2}
|
||||
strokeWidth={isSelected ? 3 : (obj.strokeWidth ?? 0)}
|
||||
rotation={obj.rotation || 0}
|
||||
draggable={draggable}
|
||||
onClick={() => {
|
||||
|
||||
Reference in New Issue
Block a user