"use client"; import { useEffect, useState } from "react"; import { Button, Modal, Segmented, Slider } from "antd"; import { RotateCcw, WandSparkles } from "lucide-react"; export type CanvasImageAngleParams = { horizontalAngle: number; pitchAngle: number; cameraDistance: number; wideAngle: boolean; }; const defaultParams: CanvasImageAngleParams = { horizontalAngle: 0, pitchAngle: 9, cameraDistance: 4.8, wideAngle: false, }; export function CanvasNodeAngleDialog({ dataUrl, open, onClose, onConfirm }: { dataUrl: string; open: boolean; onClose: () => void; onConfirm: (params: CanvasImageAngleParams) => void; }) { const [params, setParams] = useState(defaultParams); useEffect(() => { if (open) setParams(defaultParams); }, [dataUrl, open]); const update = (key: Key, value: CanvasImageAngleParams[Key]) => setParams((current) => ({ ...current, [key]: value })); return (

AI 多角度

左侧只预览方向,结果会基于原图重新生成

update("horizontalAngle", value)} /> update("pitchAngle", value)} /> update("cameraDistance", value)} />
广角镜头 update("wideAngle", value === "wide")} />
); } function AngleSlider({ label, value, min, max, step, suffix = "", onChange }: { label: string; value: number; min: number; max: number; step: number; suffix?: string; onChange: (value: number) => void; }) { return (
{label} {Number.isInteger(value) ? value : value.toFixed(1)}{suffix}
); } function previewTransform(params: CanvasImageAngleParams) { const scale = 1.08 - params.cameraDistance * 0.035 + (params.wideAngle ? -0.08 : 0); return `perspective(520px) rotateY(${params.horizontalAngle * -0.45}deg) rotateX(${params.pitchAngle * 0.35}deg) scale(${Math.max(0.72, Math.min(1.08, scale))})`; }