fix: widen scale adjust workspace guard
This commit is contained in:
parent
89b4a82e62
commit
d93a0d06d5
@ -425,6 +425,41 @@ function expandRectWithMargins(
|
||||
};
|
||||
}
|
||||
|
||||
function getRectUnion(
|
||||
leftRect: NormalizedLocalEditRegion["rect"],
|
||||
rightRect: NormalizedLocalEditRegion["rect"]
|
||||
) {
|
||||
const left = Math.min(leftRect.x, rightRect.x);
|
||||
const top = Math.min(leftRect.y, rightRect.y);
|
||||
const right = Math.max(
|
||||
leftRect.x + leftRect.width,
|
||||
rightRect.x + rightRect.width
|
||||
);
|
||||
const bottom = Math.max(
|
||||
leftRect.y + leftRect.height,
|
||||
rightRect.y + rightRect.height
|
||||
);
|
||||
return {
|
||||
x: clamp(left, 0, 1),
|
||||
y: clamp(top, 0, 1),
|
||||
width: Math.max(0.001, clamp(right, 0, 1) - clamp(left, 0, 1)),
|
||||
height: Math.max(0.001, clamp(bottom, 0, 1) - clamp(top, 0, 1)),
|
||||
};
|
||||
}
|
||||
|
||||
function rectsDifferMeaningfully(
|
||||
leftRect: NormalizedLocalEditRegion["rect"],
|
||||
rightRect: NormalizedLocalEditRegion["rect"],
|
||||
epsilon = 0.0005
|
||||
) {
|
||||
return (
|
||||
Math.abs(leftRect.x - rightRect.x) > epsilon ||
|
||||
Math.abs(leftRect.y - rightRect.y) > epsilon ||
|
||||
Math.abs(leftRect.width - rightRect.width) > epsilon ||
|
||||
Math.abs(leftRect.height - rightRect.height) > epsilon
|
||||
);
|
||||
}
|
||||
|
||||
function getScaleAdjustWorkspaceRect(
|
||||
sourceRect: NormalizedLocalEditRegion["rect"],
|
||||
targetRect: NormalizedLocalEditRegion["rect"],
|
||||
@ -432,37 +467,55 @@ function getScaleAdjustWorkspaceRect(
|
||||
) {
|
||||
const sourceWidth = Math.max(0.0001, sourceRect.width);
|
||||
const sourceHeight = Math.max(0.0001, sourceRect.height);
|
||||
const widthGrowthRatio = Math.max(0, targetRect.width / sourceWidth - 1);
|
||||
const heightGrowthRatio = Math.max(0, targetRect.height / sourceHeight - 1);
|
||||
const areaGrowthRatio = Math.max(
|
||||
0,
|
||||
const widthDeltaRatio = Math.abs(targetRect.width / sourceWidth - 1);
|
||||
const heightDeltaRatio = Math.abs(targetRect.height / sourceHeight - 1);
|
||||
const areaDeltaRatio = Math.abs(
|
||||
Math.sqrt(
|
||||
Math.max(0.0001, targetRect.width * targetRect.height) /
|
||||
Math.max(0.0001, sourceWidth * sourceHeight)
|
||||
) - 1
|
||||
);
|
||||
const explicitGrowthRatio = Math.max(
|
||||
widthGrowthRatio,
|
||||
heightGrowthRatio,
|
||||
areaGrowthRatio
|
||||
const sourceCenterX = sourceRect.x + sourceRect.width / 2;
|
||||
const sourceCenterY = sourceRect.y + sourceRect.height / 2;
|
||||
const targetCenterX = targetRect.x + targetRect.width / 2;
|
||||
const targetCenterY = targetRect.y + targetRect.height / 2;
|
||||
const movementRatioX = Math.abs(targetCenterX - sourceCenterX) / sourceWidth;
|
||||
const movementRatioY = Math.abs(targetCenterY - sourceCenterY) / sourceHeight;
|
||||
const explicitChangeRatio = Math.max(
|
||||
widthDeltaRatio,
|
||||
heightDeltaRatio,
|
||||
areaDeltaRatio,
|
||||
movementRatioX,
|
||||
movementRatioY
|
||||
);
|
||||
const fallbackScaleRatio =
|
||||
typeof scalePercent === "number" && Number.isFinite(scalePercent)
|
||||
? Math.min(1, Math.max(0, scalePercent / 100))
|
||||
? Math.min(1, Math.abs(scalePercent) / 100)
|
||||
: 0;
|
||||
const scaleRatio = Math.max(explicitGrowthRatio, fallbackScaleRatio);
|
||||
if (scaleRatio <= 0) return targetRect;
|
||||
const changeRatio = Math.max(explicitChangeRatio, fallbackScaleRatio);
|
||||
const unionRect = getRectUnion(sourceRect, targetRect);
|
||||
if (changeRatio <= 0 && !rectsDifferMeaningfully(unionRect, targetRect)) {
|
||||
return targetRect;
|
||||
}
|
||||
|
||||
const marginX = Math.min(
|
||||
0.12,
|
||||
Math.max(0.018, sourceRect.width * scaleRatio * 0.22)
|
||||
0.16,
|
||||
Math.max(
|
||||
0.018,
|
||||
unionRect.width * 0.04,
|
||||
sourceRect.width * changeRatio * 0.24
|
||||
)
|
||||
);
|
||||
const marginY = Math.min(
|
||||
0.12,
|
||||
Math.max(0.018, sourceRect.height * scaleRatio * 0.22)
|
||||
0.16,
|
||||
Math.max(
|
||||
0.018,
|
||||
unionRect.height * 0.04,
|
||||
sourceRect.height * changeRatio * 0.24
|
||||
)
|
||||
);
|
||||
|
||||
return expandRectWithMargins(targetRect, marginX, marginY);
|
||||
return expandRectWithMargins(unionRect, marginX, marginY);
|
||||
}
|
||||
|
||||
function buildScaleAdjustCompositeRegions(
|
||||
@ -476,8 +529,8 @@ function buildScaleAdjustCompositeRegions(
|
||||
targetRect,
|
||||
scalePercent
|
||||
);
|
||||
return workspaceRect.width > targetRect.width ||
|
||||
workspaceRect.height > targetRect.height
|
||||
return rectsDifferMeaningfully(workspaceRect, targetRect) &&
|
||||
rectsDifferMeaningfully(workspaceRect, region.rect)
|
||||
? [region.rect, targetRect, workspaceRect]
|
||||
: [region.rect, targetRect];
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user