fix: show scale target corner arrows

This commit is contained in:
134 2026-06-22 22:09:26 +08:00
parent 6041442662
commit 640e1b6aa6
2 changed files with 182 additions and 0 deletions

View File

@ -1630,6 +1630,101 @@ function DetailResultLocalEditDialog({
<X className="h-4 w-4" />
</button>
) : null}
{isScaleAdjustMode
? regions
.filter((region) => region.targetRect)
.map((region) => {
const sourceRect = region.rect;
const targetRect = region.targetRect as DetailResultLocalEditRect;
const markerId = `detail-scale-arrow-${region.id}`;
const connectorPoints = [
{
key: "nw",
source: { x: sourceRect.x, y: sourceRect.y },
target: { x: targetRect.x, y: targetRect.y },
},
{
key: "ne",
source: {
x: sourceRect.x + sourceRect.width,
y: sourceRect.y,
},
target: {
x: targetRect.x + targetRect.width,
y: targetRect.y,
},
},
{
key: "sw",
source: {
x: sourceRect.x,
y: sourceRect.y + sourceRect.height,
},
target: {
x: targetRect.x,
y: targetRect.y + targetRect.height,
},
},
{
key: "se",
source: {
x: sourceRect.x + sourceRect.width,
y: sourceRect.y + sourceRect.height,
},
target: {
x: targetRect.x + targetRect.width,
y: targetRect.y + targetRect.height,
},
},
];
return (
<svg
aria-hidden="true"
className="pointer-events-none absolute inset-0 z-[19] h-full w-full overflow-visible"
key={`connector-${region.id}`}
>
<defs>
<marker
id={markerId}
markerHeight="8"
markerUnits="strokeWidth"
markerWidth="8"
orient="auto"
refX="7"
refY="4"
>
<path d="M0,0 L8,4 L0,8 Z" fill="#67e8f9" />
</marker>
</defs>
{connectorPoints.map((point) => (
<line
key={`line-${point.key}`}
markerEnd={`url(#${markerId})`}
stroke="#67e8f9"
strokeDasharray="6 5"
strokeLinecap="round"
strokeWidth="2"
x1={`${point.source.x * 100}%`}
x2={`${point.target.x * 100}%`}
y1={`${point.source.y * 100}%`}
y2={`${point.target.y * 100}%`}
/>
))}
{connectorPoints.map((point) => (
<circle
cx={`${point.target.x * 100}%`}
cy={`${point.target.y * 100}%`}
fill="#ecfeff"
key={`dot-${point.key}`}
r="3.25"
stroke="#06b6d4"
strokeWidth="1.5"
/>
))}
</svg>
);
})
: null}
{isScaleAdjustMode
? regions
.filter((region) => region.targetRect)

View File

@ -2495,6 +2495,7 @@ export function ImageNode({
const targetRect = region.targetRect as NormalizedCropRect;
return {
region,
sourceStyle: getNormalizedRectOverlayStyle(region.rect, boxCutoutMetrics),
targetRect,
scalePercent: deriveCanvasScalePercentFromRects(region.rect, targetRect),
style: getNormalizedRectOverlayStyle(targetRect, boxCutoutMetrics),
@ -8591,6 +8592,92 @@ export function ImageNode({
}}
/>
) : null}
{localEditScaleTargetOverlays.map(({ region, sourceStyle, style }) => {
const sourceLeft = Number(sourceStyle.left || 0);
const sourceTop = Number(sourceStyle.top || 0);
const sourceWidth = Number(sourceStyle.width || 0);
const sourceHeight = Number(sourceStyle.height || 0);
const targetLeft = Number(style.left || 0);
const targetTop = Number(style.top || 0);
const targetWidth = Number(style.width || 0);
const targetHeight = Number(style.height || 0);
const markerId = `canvas-scale-arrow-${node.id}-${region.id}`;
const connectorPoints = [
{
key: "nw",
source: { x: sourceLeft, y: sourceTop },
target: { x: targetLeft, y: targetTop },
},
{
key: "ne",
source: { x: sourceLeft + sourceWidth, y: sourceTop },
target: { x: targetLeft + targetWidth, y: targetTop },
},
{
key: "sw",
source: { x: sourceLeft, y: sourceTop + sourceHeight },
target: { x: targetLeft, y: targetTop + targetHeight },
},
{
key: "se",
source: {
x: sourceLeft + sourceWidth,
y: sourceTop + sourceHeight,
},
target: {
x: targetLeft + targetWidth,
y: targetTop + targetHeight,
},
},
];
return (
<svg
aria-hidden="true"
className="pointer-events-none absolute inset-0 z-[161] h-full w-full overflow-visible"
key={`scale-connector-${region.id}`}
>
<defs>
<marker
id={markerId}
markerHeight="8"
markerUnits="strokeWidth"
markerWidth="8"
orient="auto"
refX="7"
refY="4"
>
<path d="M0,0 L8,4 L0,8 Z" fill="#67e8f9" />
</marker>
</defs>
{connectorPoints.map((point) => (
<line
key={`line-${point.key}`}
markerEnd={`url(#${markerId})`}
stroke="#67e8f9"
strokeDasharray="6 5"
strokeLinecap="round"
strokeWidth="2"
x1={point.source.x}
x2={point.target.x}
y1={point.source.y}
y2={point.target.y}
/>
))}
{connectorPoints.map((point) => (
<circle
cx={point.target.x}
cy={point.target.y}
fill="#ecfeff"
key={`dot-${point.key}`}
r="3.25"
stroke="#06b6d4"
strokeWidth="1.5"
/>
))}
</svg>
);
})}
{localEditScaleTargetOverlays.map(
({ region, scalePercent, style, targetRect }) => {
const left = Number(style.left || 0);