feat: redesign psd scale control and fix >100% scaling behavior
This commit is contained in:
parent
ae254d7bc5
commit
c202dd48a8
@ -83,6 +83,15 @@ const PREVIEW_VIEWPORT_PADDING = 56;
|
||||
const PREVIEW_STAGE_MAX_SCALE = 0.82;
|
||||
const PREVIEW_STAGE_TARGET_WIDTH = 760;
|
||||
const PREVIEW_STAGE_TARGET_HEIGHT = 760;
|
||||
const MIN_IMAGE_SCALE = 0.4;
|
||||
const MAX_IMAGE_SCALE = 3;
|
||||
|
||||
function clampImageScale(value: number) {
|
||||
if (!Number.isFinite(value)) {
|
||||
return 1;
|
||||
}
|
||||
return Math.max(MIN_IMAGE_SCALE, Math.min(MAX_IMAGE_SCALE, value));
|
||||
}
|
||||
|
||||
function createInitialState(template: AgentPsdTemplate | null, sourceImageUrl: string) {
|
||||
const imageAssignments: Record<string, string> = {};
|
||||
@ -692,7 +701,7 @@ export function AgentPsdTemplateEditorDialog({
|
||||
function nudgeImageScale(layerId: string, delta: number) {
|
||||
updateImagePlacement(layerId, (current) => ({
|
||||
...current,
|
||||
scale: Math.max(0.4, Math.min(3, Number((current.scale + delta).toFixed(2)))),
|
||||
scale: Number(clampImageScale(current.scale + delta).toFixed(2)),
|
||||
}));
|
||||
}
|
||||
|
||||
@ -1291,26 +1300,55 @@ export function AgentPsdTemplateEditorDialog({
|
||||
<ZoomIn className="h-3.5 w-3.5" />
|
||||
缩放
|
||||
</div>
|
||||
<span>{Math.round(selectedImagePlacement.scale * 100)}%</span>
|
||||
<span className="rounded-full border border-orange-300/35 bg-orange-500/15 px-2 py-0.5 font-medium text-orange-100">
|
||||
{Math.round(selectedImagePlacement.scale * 100)}%
|
||||
</span>
|
||||
</div>
|
||||
<div className="rounded-xl border border-white/12 bg-black/45 p-2.5">
|
||||
<div className="grid grid-cols-[34px_minmax(0,1fr)_34px] items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
className="flex h-8 w-8 items-center justify-center rounded-full border border-white/18 bg-white/[0.04] text-white transition-colors hover:bg-white/[0.12]"
|
||||
onClick={() => nudgeImageScale(selectedImageLayer.id, -0.05)}
|
||||
aria-label="缩小图片"
|
||||
title="缩小"
|
||||
>
|
||||
<ZoomOut className="h-4 w-4" />
|
||||
</button>
|
||||
<Slider
|
||||
min={MIN_IMAGE_SCALE}
|
||||
max={MAX_IMAGE_SCALE}
|
||||
step={0.01}
|
||||
value={[selectedImagePlacement.scale]}
|
||||
className="py-1"
|
||||
trackClassName="h-2.5 rounded-full border border-white/20 bg-[#0f1014]"
|
||||
rangeClassName="bg-gradient-to-r from-amber-300 via-orange-400 to-rose-400 shadow-[0_0_12px_rgba(251,146,60,0.45)]"
|
||||
thumbClassName="h-5 w-5 border-2 border-orange-100 bg-[#0a0a0d] shadow-[0_0_0_5px_rgba(251,146,60,0.22)]"
|
||||
onValueChange={(value) => {
|
||||
const newScale = clampImageScale(value[0] || 1);
|
||||
// offset 本身就是相对中心位移,缩放时不应按比例放大,否则会导致画面偏移看起来像“变形”。
|
||||
updateImagePlacement(selectedImageLayer.id, (current) => ({
|
||||
...current,
|
||||
scale: newScale,
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
className="flex h-8 w-8 items-center justify-center rounded-full border border-white/18 bg-white/[0.04] text-white transition-colors hover:bg-white/[0.12]"
|
||||
onClick={() => nudgeImageScale(selectedImageLayer.id, 0.05)}
|
||||
aria-label="放大图片"
|
||||
title="放大"
|
||||
>
|
||||
<ZoomIn className="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="mt-2 flex items-center justify-between px-0.5 text-[10px] text-white/45">
|
||||
<span>40%</span>
|
||||
<span className="text-orange-200">100%</span>
|
||||
<span>300%</span>
|
||||
</div>
|
||||
</div>
|
||||
<Slider
|
||||
min={0.4}
|
||||
max={3}
|
||||
step={0.01}
|
||||
value={[selectedImagePlacement.scale]}
|
||||
onValueChange={(value) => {
|
||||
const newScale = value[0] || 1;
|
||||
updateImagePlacement(selectedImageLayer.id, (current) => {
|
||||
// 以中心点缩放,调整偏移量保持中心位置不变
|
||||
const scaleDiff = newScale / current.scale;
|
||||
return {
|
||||
scale: newScale,
|
||||
offsetX: current.offsetX * scaleDiff,
|
||||
offsetY: current.offsetY * scaleDiff,
|
||||
};
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Button
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user