fix blur in viewer

This commit is contained in:
hamid zarghami
2026-07-11 09:10:41 +03:30
parent c6bb275d05
commit 9e105606a3
2 changed files with 48 additions and 8 deletions
+10 -2
View File
@@ -33,8 +33,16 @@ export function computeBlurOverlayGeometry(
): BlurOverlayGeometry { ): BlurOverlayGeometry {
const rotation = obj.rotation ?? 0; const rotation = obj.rotation ?? 0;
const shapeType = obj.shapeType ?? "square"; const shapeType = obj.shapeType ?? "square";
const anchorX = livePosition?.x ?? (obj.x ?? 0) * scale; const anchorX =
const anchorY = livePosition?.y ?? (obj.y ?? 0) * scale; livePosition?.x ??
(shapeType === "triangle" || shapeType === "abstract"
? ((obj.x ?? 0) + (obj.width ?? 100) / 2) * scale
: (obj.x ?? 0) * scale);
const anchorY =
livePosition?.y ??
(shapeType === "triangle" || shapeType === "abstract"
? ((obj.y ?? 0) + (obj.height ?? 100) / 2) * scale
: (obj.y ?? 0) * scale);
if (shapeType === "circle") { if (shapeType === "circle") {
const sizePx = (obj.width ?? 100) * scale; const sizePx = (obj.width ?? 100) * scale;
+38 -6
View File
@@ -11,7 +11,11 @@ import {
resolveTextMaxWidth, resolveTextMaxWidth,
usesWrappedLayout, usesWrappedLayout,
} from '@/pages/editor/utils/textStyle'; } from '@/pages/editor/utils/textStyle';
import { getCssBlurStyle } from '@/pages/editor/utils/shapeBlur'; import {
buildBlurOverlayStyle,
buildBlurStackEntries,
isBlurBackdropObject,
} from '@/pages/editor/utils/blurOverlayLayout';
import { getCssBorderRadius } from '@/pages/editor/utils/borderRadius'; import { getCssBorderRadius } from '@/pages/editor/utils/borderRadius';
import '@/pages/viewer/styles/entranceAnimations.css'; import '@/pages/viewer/styles/entranceAnimations.css';
import { mergeEntranceAnimationStyle } from '@/pages/viewer/utils/entranceAnimationStyle'; import { mergeEntranceAnimationStyle } from '@/pages/viewer/utils/entranceAnimationStyle';
@@ -213,11 +217,15 @@ const BookPage = memo(forwardRef<HTMLDivElement, BookPageProps>(
return null; return null;
} }
// Blur shapes use backdrop-filter overlays (see blur stack below), not CSS filter on the shape.
if (isBlurBackdropObject(obj)) {
return null;
}
const objectFillStyle: React.CSSProperties = const objectFillStyle: React.CSSProperties =
obj.fillType === 'gradient' && obj.gradient obj.fillType === 'gradient' && obj.gradient
? { backgroundImage: toCssLinearGradient(obj.gradient) } ? { backgroundImage: toCssLinearGradient(obj.gradient) }
: { backgroundColor: obj.fill || 'transparent' }; : { backgroundColor: obj.fill || 'transparent' };
const shapeBlurStyle = getCssBlurStyle(obj.blur, scale);
switch (obj.type) { switch (obj.type) {
case 'text': { case 'text': {
@@ -537,7 +545,6 @@ const BookPage = memo(forwardRef<HTMLDivElement, BookPageProps>(
height: `${radius * 2}px`, height: `${radius * 2}px`,
borderRadius: '50%', borderRadius: '50%',
...objectFillStyle, ...objectFillStyle,
...shapeBlurStyle,
border: hasStroke && obj.stroke border: hasStroke && obj.stroke
? `${actualStrokeWidth * scale}px solid ${obj.stroke}` ? `${actualStrokeWidth * scale}px solid ${obj.stroke}`
: 'none', : 'none',
@@ -610,7 +617,6 @@ const BookPage = memo(forwardRef<HTMLDivElement, BookPageProps>(
width: `${size}px`, width: `${size}px`,
height: `${size}px`, height: `${size}px`,
opacity: (obj.opacity ?? 100) / 100, opacity: (obj.opacity ?? 100) / 100,
...shapeBlurStyle,
transform: obj.rotation ? `rotate(${obj.rotation}deg)` : undefined, transform: obj.rotation ? `rotate(${obj.rotation}deg)` : undefined,
transformOrigin: 'center center', transformOrigin: 'center center',
zIndex: index, zIndex: index,
@@ -669,7 +675,6 @@ const BookPage = memo(forwardRef<HTMLDivElement, BookPageProps>(
height: `${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%)', clipPath: 'polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%)',
...objectFillStyle, ...objectFillStyle,
...shapeBlurStyle,
border: obj.stroke border: obj.stroke
? `${(obj.strokeWidth || 1) * scale}px solid ${obj.stroke}` ? `${(obj.strokeWidth || 1) * scale}px solid ${obj.stroke}`
: 'none', : 'none',
@@ -692,7 +697,6 @@ const BookPage = memo(forwardRef<HTMLDivElement, BookPageProps>(
width: `${(obj.width || 100) * scale}px`, width: `${(obj.width || 100) * scale}px`,
height: `${(obj.height || 100) * scale}px`, height: `${(obj.height || 100) * scale}px`,
...objectFillStyle, ...objectFillStyle,
...shapeBlurStyle,
borderRadius: `${Math.max(0, (obj.borderRadius || 0) * scale)}px`, borderRadius: `${Math.max(0, (obj.borderRadius || 0) * scale)}px`,
border: hasStroke && obj.stroke border: hasStroke && obj.stroke
? `${actualStrokeWidth * scale}px solid ${obj.stroke}` ? `${actualStrokeWidth * scale}px solid ${obj.stroke}`
@@ -1102,6 +1106,34 @@ const BookPage = memo(forwardRef<HTMLDivElement, BookPageProps>(
)} )}
<div style={{ position: 'absolute', inset: 0, zIndex: 1 }}> <div style={{ position: 'absolute', inset: 0, zIndex: 1 }}>
{page.elements.map((element, index) => renderObject(element, index, page.elements))} {page.elements.map((element, index) => renderObject(element, index, page.elements))}
{buildBlurStackEntries(page.elements).map((entry) => {
const blurIndex = page.elements.findIndex((el) => el.id === entry.blurObject.id);
const blurOverlayStyle = buildBlurOverlayStyle(entry.blurObject, scale);
return (
<div
key={`blur-stack-${entry.key}`}
style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}
>
<div
style={withEntrance(
blurOverlayStyle,
entry.blurObject,
blurIndex >= 0 ? blurIndex : 0,
{
transformOrigin: blurOverlayStyle.transformOrigin,
rotationDeg: entry.blurObject.rotation ?? 0,
},
)}
/>
{entry.occlusionObjects.map((obj) => {
const index = page.elements.findIndex((el) => el.id === obj.id);
if (index < 0) return null;
return renderObject(obj, index, page.elements);
})}
</div>
);
})}
</div> </div>
</div> </div>
{showLoadingOverlay && ( {showLoadingOverlay && (