grediant in a shape

This commit is contained in:
hamid zarghami
2026-05-09 09:50:13 +03:30
parent 0229a1355d
commit b513ecb33f
16 changed files with 378 additions and 15 deletions
+39 -6
View File
@@ -1,6 +1,7 @@
import { forwardRef } from 'react';
import { type PageData } from '../types';
import type { EditorObject } from '@/pages/editor/store/editorStore';
import { toCssLinearGradient } from '@/pages/editor/utils/gradient';
type BookPageProps = {
page: PageData;
@@ -8,8 +9,13 @@ type BookPageProps = {
pageWidth?: number;
pageHeight?: number;
onLinkClick?: (linkUrl: string) => void;
backgroundType?: 'color' | 'image';
backgroundType?: 'color' | 'gradient' | 'image';
backgroundColor?: string;
backgroundGradient?: {
from: string;
to: string;
angle: number;
};
backgroundImageUrl?: string;
};
@@ -21,7 +27,7 @@ type BookPageProps = {
* نیاز به forwardRef دارد تا react-pageflip بتواند ref را مدیریت کند
*/
const BookPage = forwardRef<HTMLDivElement, BookPageProps>(
({ page, scale = 1, pageWidth, pageHeight, onLinkClick, backgroundType, backgroundColor, backgroundImageUrl }, ref) => {
({ page, scale = 1, pageWidth, pageHeight, onLinkClick, backgroundType, backgroundColor, backgroundGradient, backgroundImageUrl }, ref) => {
// تابع برای تبدیل opacity به رنگ (مثل editor)
// در editor، getColorWithOpacity انتظار opacity 0-100 دارد
// در dataTransformer، opacity از 0-1 به 0-100 تبدیل شده است
@@ -69,6 +75,11 @@ const BookPage = forwardRef<HTMLDivElement, BookPageProps>(
return null;
}
const objectFillStyle: React.CSSProperties =
obj.fillType === 'gradient' && obj.gradient
? { backgroundImage: toCssLinearGradient(obj.gradient) }
: { backgroundColor: obj.fill || 'transparent' };
switch (obj.type) {
case 'text': {
// برای text، opacity در رنگ اعمال می‌شود، پس باید opacity را از baseStyle حذف کنیم
@@ -234,7 +245,7 @@ const BookPage = forwardRef<HTMLDivElement, BookPageProps>(
width: `${radius * 2}px`,
height: `${radius * 2}px`,
borderRadius: '50%',
backgroundColor: obj.fill || 'transparent',
...objectFillStyle,
border: hasStroke && obj.stroke
? `${actualStrokeWidth * scale}px solid ${obj.stroke}`
: 'none',
@@ -280,6 +291,7 @@ const BookPage = forwardRef<HTMLDivElement, BookPageProps>(
const strokeWidth = hasStroke && obj.stroke ? actualStrokeWidth * scale : 0;
const fillColor = obj.fill || '#000000';
const strokeColor = obj.stroke || 'transparent';
const gradientId = `triangle-grad-${obj.id}-${index}`;
return (
<svg
@@ -298,9 +310,25 @@ const BookPage = forwardRef<HTMLDivElement, BookPageProps>(
}}
viewBox={`0 0 ${size} ${size}`}
>
{obj.fillType === 'gradient' && obj.gradient ? (
<defs>
<linearGradient
id={gradientId}
gradientUnits="userSpaceOnUse"
x1="0"
y1="0"
x2={size}
y2={size}
gradientTransform={`rotate(${obj.gradient.angle}, ${size / 2}, ${size / 2})`}
>
<stop offset="0%" stopColor={obj.gradient.from} />
<stop offset="100%" stopColor={obj.gradient.to} />
</linearGradient>
</defs>
) : null}
<polygon
points={`${topX},${topY} ${bottomLeftX},${bottomY} ${bottomRightX},${bottomY}`}
fill={fillColor}
fill={obj.fillType === 'gradient' && obj.gradient ? `url(#${gradientId})` : fillColor}
stroke={strokeColor}
strokeWidth={strokeWidth}
/>
@@ -328,7 +356,7 @@ const BookPage = forwardRef<HTMLDivElement, BookPageProps>(
width: `${radius * 2}px`,
height: `${radius * 2}px`,
clipPath: 'polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%)',
backgroundColor: obj.fill || 'transparent',
...objectFillStyle,
border: obj.stroke
? `${(obj.strokeWidth || 1) * scale}px solid ${obj.stroke}`
: 'none',
@@ -346,7 +374,7 @@ const BookPage = forwardRef<HTMLDivElement, BookPageProps>(
...baseStyle,
width: `${(obj.width || 100) * scale}px`,
height: `${(obj.height || 100) * scale}px`,
backgroundColor: obj.fill || 'transparent',
...objectFillStyle,
borderRadius: `${Math.max(0, (obj.borderRadius || 0) * scale)}px`,
border: hasStroke && obj.stroke
? `${actualStrokeWidth * scale}px solid ${obj.stroke}`
@@ -489,6 +517,7 @@ const BookPage = forwardRef<HTMLDivElement, BookPageProps>(
const effectiveBackgroundType = backgroundType ?? page.backgroundType ?? 'color';
const effectiveBackgroundColor = backgroundColor ?? page.backgroundColor ?? '#ffffff';
const effectiveBackgroundGradient = backgroundGradient ?? page.backgroundGradient;
const effectiveBackgroundImageUrl = backgroundImageUrl ?? page.backgroundImageUrl ?? '';
const bgStyle: React.CSSProperties =
@@ -499,6 +528,10 @@ const BookPage = forwardRef<HTMLDivElement, BookPageProps>(
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
}
: effectiveBackgroundType === 'gradient' && effectiveBackgroundGradient
? {
backgroundImage: toCssLinearGradient(effectiveBackgroundGradient),
}
: { backgroundColor: effectiveBackgroundColor };
return (