fix(canvas): move compare toggle and enable hover-to-slide mode
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-03-01 02:09:28 +08:00
parent 22493ce1a2
commit a1035c5dae

View File

@ -283,7 +283,6 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) {
const [isAddingToChat, setIsAddingToChat] = useState(false);
const [isCompareMode, setIsCompareMode] = useState(false);
const [compareSplitPercent, setCompareSplitPercent] = useState(50);
const [isCompareDragging, setIsCompareDragging] = useState(false);
// 文件输入的 ref
const fileInputRef = useRef<HTMLInputElement>(null);
@ -379,17 +378,32 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) {
setIsEditingTitle(false);
setPromptDialogOpen(false);
setIsCompareMode(false);
setIsCompareDragging(false);
}
}, [isSelected]);
useEffect(() => {
if (!hasCompareSource || isThisNodePicking) {
setIsCompareMode(false);
setIsCompareDragging(false);
}
}, [hasCompareSource, isThisNodePicking]);
useEffect(() => {
if (!isCompareMode) return;
const handlePointerDownOutside = (event: PointerEvent) => {
const target = event.target as Node | null;
if (!target) return;
const container = containerRef.current;
if (container && container.contains(target)) return;
setIsCompareMode(false);
};
document.addEventListener("pointerdown", handlePointerDownOutside, true);
return () => {
document.removeEventListener("pointerdown", handlePointerDownOutside, true);
};
}, [isCompareMode]);
useEffect(() => {
if (!isEditingTitle) {
setDraftTitle(getImageNodeTitle(data, node.id));
@ -1575,12 +1589,16 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) {
<div className="relative w-full h-full">
{isCompareMode && hasCompareSource ? (
<div
className={cn(
"relative h-full w-full overflow-hidden bg-muted/30 select-none",
isCompareDragging ? "cursor-col-resize" : "cursor-default"
)}
className="relative h-full w-full overflow-hidden bg-muted/30 select-none cursor-col-resize"
style={{ touchAction: "none" }}
data-canvas-no-drag="true"
onPointerDown={(event) => {
event.stopPropagation();
updateCompareSplitByClientX(event.clientX);
}}
onPointerMove={(event) => {
updateCompareSplitByClientX(event.clientX);
}}
>
<img
src={compareSource}
@ -1605,53 +1623,13 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) {
className="pointer-events-none absolute inset-y-0 z-30 w-[2px] bg-white/90 shadow-[0_0_0_1px_rgba(0,0,0,0.45),0_0_14px_rgba(255,255,255,0.55)]"
style={{ left: `${compareSplitPercent}%`, transform: "translateX(-50%)" }}
/>
<button
type="button"
className="absolute top-1/2 z-40 h-7 w-7 -translate-x-1/2 -translate-y-1/2 cursor-col-resize rounded-full border border-white/85 bg-black/70 text-white"
<div
className="pointer-events-none absolute top-1/2 z-40 h-7 w-7 -translate-x-1/2 -translate-y-1/2 rounded-full border border-white/85 bg-black/70 text-white flex items-center justify-center"
style={{ left: `${compareSplitPercent}%` }}
data-canvas-no-drag="true"
tabIndex={-1}
title="拖动中线查看对比"
aria-label="拖动中线查看对比"
aria-hidden="true"
>
&lt;&gt;
</button>
<input
type="range"
min={0}
max={100}
step={0.1}
value={compareSplitPercent}
data-canvas-no-drag="true"
aria-label="新旧图对比滑块"
className="absolute inset-0 z-50 h-full w-full cursor-col-resize appearance-none bg-transparent opacity-0"
onPointerDown={(event) => {
event.stopPropagation();
setIsCompareDragging(true);
}}
onPointerUp={(event) => {
event.stopPropagation();
setIsCompareDragging(false);
}}
onPointerCancel={() => {
setIsCompareDragging(false);
}}
onClick={(event) => {
event.stopPropagation();
}}
onInput={(event) => {
const value = Number((event.target as HTMLInputElement).value);
if (!Number.isNaN(value)) {
setCompareSplitPercent(Math.max(0, Math.min(100, value)));
}
}}
onChange={(event) => {
const value = Number(event.target.value);
if (!Number.isNaN(value)) {
setCompareSplitPercent(Math.max(0, Math.min(100, value)));
}
}}
/>
</div>
<div className="pointer-events-none absolute left-2 top-2 rounded bg-black/55 px-1.5 py-0.5 text-[10px] text-white">
原图
</div>
@ -1716,7 +1694,7 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) {
{isSelected && !isMultiSelected && hasCompareSource && !isThisNodePicking && (
<button
type="button"
className="absolute top-2 right-2 z-40 inline-flex h-8 w-8 items-center justify-center rounded-full border border-white/70 bg-black/70 text-white transition-colors hover:bg-black/80"
className="absolute bottom-2 right-2 z-[140] inline-flex h-8 w-8 items-center justify-center rounded-full border border-white/70 bg-black/70 text-white transition-colors hover:bg-black/80"
onPointerDown={(event) => {
event.stopPropagation();
}}