fix text shape place

This commit is contained in:
hamid zarghami
2026-01-07 10:11:10 +03:30
parent 9479a3425b
commit 9237bf0ba4
3 changed files with 86 additions and 45 deletions
+46 -9
View File
@@ -15,6 +15,35 @@ type BookPageProps = {
* نیاز به forwardRef دارد تا react-pageflip بتواند ref را مدیریت کند
*/
const BookPage = forwardRef<HTMLDivElement, BookPageProps>(({ page, scale = 1 }, ref) => {
// تابع برای تبدیل opacity به رنگ (مثل editor)
// در editor، getColorWithOpacity انتظار opacity 0-100 دارد
// در dataTransformer، opacity از 0-1 به 0-100 تبدیل شده است
// پس opacity را مستقیماً استفاده می‌کنیم
const getColorWithOpacity = (fill?: string, opacity?: number): string => {
if (!fill) return '#000000';
// opacity در EditorObject به صورت 0-100 است (بعد از تبدیل در dataTransformer)
// در editor getColorWithOpacity انتظار 0-100 دارد
const opacityValue = opacity !== undefined ? opacity : 100;
// اگر opacity 100% باشد، رنگ را بدون تغییر برگردان (مثل editor)
if (opacityValue >= 100) return fill;
const hex = fill.replace('#', '');
// اگر hex کوتاه‌تر از 6 کاراکتر باشد، padding اضافه کن
const paddedHex = hex.length === 3
? hex.split('').map(char => char + char).join('')
: hex;
const r = parseInt(paddedHex.substring(0, 2), 16);
const g = parseInt(paddedHex.substring(2, 4), 16);
const b = parseInt(paddedHex.substring(4, 6), 16);
// opacityValue را به alpha تبدیل کن (0-100 -> 0-1) مثل editor
const alpha = opacityValue / 100;
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
};
const renderObject = (obj: EditorObject, index: number) => {
const baseStyle: React.CSSProperties = {
position: 'absolute',
@@ -30,16 +59,19 @@ const BookPage = forwardRef<HTMLDivElement, BookPageProps>(({ page, scale = 1 },
}
switch (obj.type) {
case 'text':
case 'text': {
// برای text، opacity در رنگ اعمال می‌شود، پس باید opacity را از baseStyle حذف کنیم
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { opacity, ...textBaseStyle } = baseStyle;
return (
<div
key={obj.id || index}
style={{
...baseStyle,
...textBaseStyle,
fontSize: `${(obj.fontSize || 16) * scale}px`,
fontFamily: obj.fontFamily || 'irancell, sans-serif',
fontWeight: obj.fontWeight || 'normal',
color: obj.fill || '#000000',
color: getColorWithOpacity(obj.fill, obj.opacity),
whiteSpace: 'pre-wrap',
letterSpacing: obj.letterSpacing ? `${obj.letterSpacing * scale}px` : undefined,
}}
@@ -47,6 +79,7 @@ const BookPage = forwardRef<HTMLDivElement, BookPageProps>(({ page, scale = 1 },
{obj.text || ''}
</div>
);
}
case 'image':
return (
@@ -58,7 +91,8 @@ const BookPage = forwardRef<HTMLDivElement, BookPageProps>(({ page, scale = 1 },
...baseStyle,
width: obj.width ? `${obj.width * scale}px` : 'auto',
height: obj.height ? `${obj.height * scale}px` : 'auto',
objectFit: 'contain',
objectFit: 'fill', // مشابه Konva که image را با width و height مشخص شده رندر می‌کند
zIndex: index, // برای حفظ ترتیب رندر
}}
/>
);
@@ -102,15 +136,14 @@ const BookPage = forwardRef<HTMLDivElement, BookPageProps>(({ page, scale = 1 },
</a>
);
case 'rectangle':
case 'rectangle': {
if (obj.shapeType === 'circle') {
// در editor، circle با مرکز در x, y رندر می‌شود (radius = width/2)
// اما در viewer-data.json ممکن است x, y به عنوان گوشه بالا-چپ bounding box باشد
// برای سازگاری با editor، فرض می‌کنیم x, y مرکز است
// در dataTransformer از گوشه بالا-چپ به مرکز تبدیل شده است
const radius = ((obj.width || 100) / 2) * scale;
const centerX = (obj.x || 0) * scale;
const centerY = (obj.y || 0) * scale;
return (
<div
key={obj.id || index}
@@ -128,6 +161,7 @@ const BookPage = forwardRef<HTMLDivElement, BookPageProps>(({ page, scale = 1 },
opacity: obj.opacity ?? 1,
transform: obj.rotation ? `rotate(${obj.rotation}deg)` : undefined,
transformOrigin: 'center center',
zIndex: index, // برای حفظ ترتیب رندر
}}
/>
);
@@ -204,9 +238,11 @@ const BookPage = forwardRef<HTMLDivElement, BookPageProps>(({ page, scale = 1 },
border: obj.stroke
? `${(obj.strokeWidth || 1) * scale}px solid ${obj.stroke}`
: 'none',
zIndex: index, // برای حفظ ترتیب رندر
};
return <div key={obj.id || index} style={shapeStyle} />;
}
case 'line': {
// در EditorObject، width و height به عنوان مختصات انتهایی استفاده می‌شوند
@@ -283,7 +319,7 @@ const BookPage = forwardRef<HTMLDivElement, BookPageProps>(({ page, scale = 1 },
);
}
case 'grid':
case 'grid': {
if (!obj.tableData) return null;
const { rows, cols, cells, cellWidth, cellHeight, stroke, strokeWidth } =
@@ -325,6 +361,7 @@ const BookPage = forwardRef<HTMLDivElement, BookPageProps>(({ page, scale = 1 },
)}
</div>
);
}
default:
return null;