feat: add on-canvas zoom controls for psd image slots
This commit is contained in:
parent
dc04c1d91b
commit
dceebf0652
@ -9,10 +9,12 @@ import {
|
||||
Loader2,
|
||||
Move,
|
||||
MousePointerClick,
|
||||
RefreshCcw,
|
||||
Sparkles,
|
||||
Type,
|
||||
Upload,
|
||||
ZoomIn,
|
||||
ZoomOut,
|
||||
} from "lucide-react";
|
||||
import { fetchUploadWithRetry } from "@/lib/client/upload-with-retry";
|
||||
import {
|
||||
@ -565,6 +567,20 @@ 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)))),
|
||||
}));
|
||||
}
|
||||
|
||||
function resetImagePlacement(layerId: string) {
|
||||
setImagePlacements((current) => ({
|
||||
...current,
|
||||
[layerId]: getDefaultAgentPsdImagePlacement(),
|
||||
}));
|
||||
}
|
||||
|
||||
function handleImageDragStart(
|
||||
layer: AgentPsdTemplateImageLayerSlot,
|
||||
event: ReactPointerEvent<HTMLDivElement>
|
||||
@ -611,6 +627,21 @@ export function AgentPsdTemplateEditorDialog({
|
||||
window.addEventListener("pointercancel", handlePointerUp);
|
||||
}
|
||||
|
||||
function handleImageWheel(
|
||||
layer: AgentPsdTemplateImageLayerSlot,
|
||||
event: ReactPointerEvent<HTMLDivElement>
|
||||
) {
|
||||
if (!String(effectiveImageAssignments[layer.id] || "").trim()) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
const delta = event.deltaY < 0 ? 0.08 : -0.08;
|
||||
nudgeImageScale(layer.id, delta);
|
||||
}
|
||||
|
||||
async function handleRender() {
|
||||
if (!selectedTemplate) {
|
||||
toast.error("请先选择 PSD 模板");
|
||||
@ -898,6 +929,7 @@ export function AgentPsdTemplateEditorDialog({
|
||||
tabIndex={0}
|
||||
onClick={() => setSelectedLayerId(layer.id)}
|
||||
onPointerDown={(event) => handleImageDragStart(layer, event)}
|
||||
onWheel={(event) => handleImageWheel(layer, event)}
|
||||
className="absolute overflow-hidden rounded-lg transition-all"
|
||||
style={{
|
||||
...frameStyle,
|
||||
@ -912,9 +944,50 @@ export function AgentPsdTemplateEditorDialog({
|
||||
<div className="absolute left-2 top-2 rounded-full bg-black/70 px-2 py-1 text-[11px] text-white">
|
||||
{layer.layerName}
|
||||
</div>
|
||||
<div className="absolute right-2 top-2 flex items-center gap-1 rounded-full bg-black/70 p-1 text-white shadow-lg">
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-full p-1 transition hover:bg-white/10"
|
||||
onPointerDown={(event) => event.stopPropagation()}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
nudgeImageScale(layer.id, -0.1);
|
||||
}}
|
||||
aria-label="缩小图片"
|
||||
title="缩小"
|
||||
>
|
||||
<ZoomOut className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-full p-1 transition hover:bg-white/10"
|
||||
onPointerDown={(event) => event.stopPropagation()}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
nudgeImageScale(layer.id, 0.1);
|
||||
}}
|
||||
aria-label="放大图片"
|
||||
title="放大"
|
||||
>
|
||||
<ZoomIn className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-full p-1 transition hover:bg-white/10"
|
||||
onPointerDown={(event) => event.stopPropagation()}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
resetImagePlacement(layer.id);
|
||||
}}
|
||||
aria-label="重置图片位置和缩放"
|
||||
title="重置"
|
||||
>
|
||||
<RefreshCcw className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="pointer-events-none absolute bottom-2 right-2 flex items-center gap-1 rounded-full bg-orange-500/85 px-2 py-1 text-[11px] text-white">
|
||||
<Move className="h-3 w-3" />
|
||||
拖动调整
|
||||
拖动或滚轮缩放
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
@ -1102,12 +1175,7 @@ export function AgentPsdTemplateEditorDialog({
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() =>
|
||||
setImagePlacements((current) => ({
|
||||
...current,
|
||||
[selectedImageLayer.id]: getDefaultAgentPsdImagePlacement(),
|
||||
}))
|
||||
}
|
||||
onClick={() => resetImagePlacement(selectedImageLayer.id)}
|
||||
>
|
||||
重置位置与缩放
|
||||
</Button>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user