fix: portal local edit prompts outside canvas transforms
This commit is contained in:
parent
9ddae7423e
commit
852498b6bb
@ -2057,8 +2057,12 @@ export function ImageNode({
|
||||
// 文件输入的 ref
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const [localEditPromptLayerElement, setLocalEditPromptLayerElement] =
|
||||
useState<HTMLDivElement | null>(null);
|
||||
const [localEditPromptPortalFrame, setLocalEditPromptPortalFrame] = useState<{
|
||||
left: number;
|
||||
top: number;
|
||||
width: number;
|
||||
height: number;
|
||||
} | null>(null);
|
||||
const displayImageRef = useRef<HTMLImageElement>(null);
|
||||
const compareFrameRef = useRef<HTMLDivElement>(null);
|
||||
const cropOverlayRef = useRef<HTMLDivElement>(null);
|
||||
@ -2493,6 +2497,59 @@ export function ImageNode({
|
||||
})),
|
||||
[localEditPromptInlineOverlays, nodeContentScale]
|
||||
);
|
||||
useEffect(() => {
|
||||
if (
|
||||
!localEditMode ||
|
||||
!data.src ||
|
||||
localEditPromptViewportOverlays.length === 0 ||
|
||||
typeof window === "undefined"
|
||||
) {
|
||||
setLocalEditPromptPortalFrame(null);
|
||||
return;
|
||||
}
|
||||
|
||||
let animationFrame = 0;
|
||||
const updatePortalFrame = () => {
|
||||
const rect = containerRef.current?.getBoundingClientRect();
|
||||
if (!rect) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextFrame = {
|
||||
left: rect.left,
|
||||
top: rect.top,
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
};
|
||||
setLocalEditPromptPortalFrame((currentFrame) => {
|
||||
if (
|
||||
currentFrame &&
|
||||
Math.abs(currentFrame.left - nextFrame.left) < 0.5 &&
|
||||
Math.abs(currentFrame.top - nextFrame.top) < 0.5 &&
|
||||
Math.abs(currentFrame.width - nextFrame.width) < 0.5 &&
|
||||
Math.abs(currentFrame.height - nextFrame.height) < 0.5
|
||||
) {
|
||||
return currentFrame;
|
||||
}
|
||||
return nextFrame;
|
||||
});
|
||||
};
|
||||
const schedulePortalFrameUpdate = () => {
|
||||
window.cancelAnimationFrame(animationFrame);
|
||||
animationFrame = window.requestAnimationFrame(updatePortalFrame);
|
||||
};
|
||||
|
||||
updatePortalFrame();
|
||||
const intervalId = window.setInterval(updatePortalFrame, 250);
|
||||
window.addEventListener("resize", schedulePortalFrameUpdate);
|
||||
window.addEventListener("scroll", schedulePortalFrameUpdate, true);
|
||||
return () => {
|
||||
window.cancelAnimationFrame(animationFrame);
|
||||
window.clearInterval(intervalId);
|
||||
window.removeEventListener("resize", schedulePortalFrameUpdate);
|
||||
window.removeEventListener("scroll", schedulePortalFrameUpdate, true);
|
||||
};
|
||||
}, [data.src, localEditMode, localEditPromptViewportOverlays.length]);
|
||||
const currentPickerClickStyle = useMemo(() => {
|
||||
if (!boxCutoutMetrics || !currentClick) return null;
|
||||
|
||||
@ -8147,10 +8204,20 @@ export function ImageNode({
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{localEditPromptLayerElement
|
||||
{typeof document !== "undefined" && localEditPromptPortalFrame
|
||||
? createPortal(
|
||||
localEditPromptViewportOverlays.map(
|
||||
({ region, isEditing, style }) => (
|
||||
<div
|
||||
className="pointer-events-none fixed z-[9998] overflow-visible"
|
||||
data-local-edit-control="true"
|
||||
style={{
|
||||
left: localEditPromptPortalFrame.left,
|
||||
top: localEditPromptPortalFrame.top,
|
||||
width: localEditPromptPortalFrame.width,
|
||||
height: localEditPromptPortalFrame.height,
|
||||
}}
|
||||
>
|
||||
{localEditPromptViewportOverlays.map(
|
||||
({ region, isEditing, style }) => (
|
||||
<div
|
||||
className="nodrag nopan nowheel pointer-events-auto absolute z-[170] flex flex-col items-stretch gap-1.5"
|
||||
data-canvas-no-drag="true"
|
||||
@ -8435,9 +8502,10 @@ export function ImageNode({
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
),
|
||||
localEditPromptLayerElement
|
||||
)
|
||||
)}
|
||||
</div>,
|
||||
document.body
|
||||
)
|
||||
: null}
|
||||
{localEditDraftRectStyle ? (
|
||||
@ -8829,10 +8897,6 @@ export function ImageNode({
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
<div
|
||||
className="pointer-events-none absolute inset-0 z-[260] overflow-visible"
|
||||
ref={setLocalEditPromptLayerElement}
|
||||
/>
|
||||
</div>
|
||||
<AgentExecutionSnapshotDialog
|
||||
onOpenChange={setSnapshotDialogOpen}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user