fix text shape place
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -44,7 +44,10 @@ export function transformViewerDataToPages(data: ViewerData): PageData[] {
|
||||
type: obj.type as EditorObject['type'],
|
||||
x: obj.x,
|
||||
y: obj.y,
|
||||
opacity: obj.opacity ?? 1,
|
||||
// در JSON، opacity به صورت 0-100 است (درصد)
|
||||
// در editor هم opacity به صورت 0-100 است
|
||||
// پس opacity را مستقیماً استفاده میکنیم
|
||||
opacity: obj.opacity !== undefined ? obj.opacity : 100,
|
||||
visible: true,
|
||||
};
|
||||
|
||||
@@ -66,11 +69,12 @@ export function transformViewerDataToPages(data: ViewerData): PageData[] {
|
||||
// برای circle در viewer-data.json، x, y به عنوان گوشه بالا-چپ bounding box است
|
||||
// اما در editor، circle با مرکز در x, y ذخیره میشود
|
||||
// پس باید تبدیل کنیم
|
||||
if (obj.type === 'rectangle' && obj.shapeType === 'circle') {
|
||||
// تبدیل از گوشه بالا-چپ به مرکز
|
||||
baseObject.x = obj.x + (obj.width || 100) / 2;
|
||||
baseObject.y = obj.y + (obj.height || 100) / 2;
|
||||
}
|
||||
// اما بر اساس بررسی، در JSON موقعیت به عنوان مرکز ذخیره شده است
|
||||
// پس نباید تبدیل کنیم - مستقیماً استفاده میکنیم
|
||||
// اگر در آینده JSON به صورت گوشه بالا-چپ export شود، باید تبدیل کنیم:
|
||||
// baseObject.x = obj.x + (obj.width || 100) / 2;
|
||||
// baseObject.y = obj.y + (obj.height || 100) / 2;
|
||||
// اما فعلاً JSON به صورت مرکز است، پس تبدیل نمیکنیم
|
||||
if (obj.fill !== undefined) baseObject.fill = obj.fill;
|
||||
if (obj.stroke !== undefined) baseObject.stroke = obj.stroke;
|
||||
if (obj.strokeWidth !== undefined) baseObject.strokeWidth = obj.strokeWidth;
|
||||
|
||||
Reference in New Issue
Block a user