33270dd026
CI/CD Pipeline / Check if frontend-only change (push) Has been cancelled
CI/CD Pipeline / Validate - Code Quality (push) Has been cancelled
CI/CD Pipeline / Validate - Type Check (mypy) (push) Has been cancelled
CI/CD Pipeline / Validate - Migration (alembic) (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Lint (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / PR Build API Image (push) Has been cancelled
CI/CD Pipeline / PR Build Web Image (push) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (push) Has been cancelled
CI/CD Pipeline / Build Staging API Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com> Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
131 lines
3.9 KiB
TypeScript
Executable File
131 lines
3.9 KiB
TypeScript
Executable File
/**
|
|
* 选中贴纸的属性编辑器
|
|
*/
|
|
import React from "react"
|
|
import type { StickerItem } from "@/pages/editing-planner/types"
|
|
import { StickerPreview } from "./StickerPreview"
|
|
import { TextStickerPropsEditor } from "./TextStickerPropsEditor"
|
|
|
|
interface StickerPropsEditorProps {
|
|
sticker: StickerItem
|
|
totalDuration: number
|
|
onUpdate: (id: string, partial: Partial<StickerItem>) => void
|
|
}
|
|
|
|
const StickerPropsEditor: React.FC<StickerPropsEditorProps> = ({
|
|
sticker,
|
|
totalDuration,
|
|
onUpdate,
|
|
}) => {
|
|
return (
|
|
<div className="sticker-props-section">
|
|
<div className="sticker-section-title">属性调整</div>
|
|
|
|
{/* 位置 */}
|
|
<div className="sticker-prop-row">
|
|
<span className="sticker-prop-label">位置 X</span>
|
|
<input
|
|
type="range"
|
|
className="sticker-prop-slider"
|
|
min={0}
|
|
max={100}
|
|
value={sticker.x}
|
|
onChange={(e) => onUpdate(sticker.id, { x: Number(e.target.value) })}
|
|
/>
|
|
<span className="sticker-prop-value">{sticker.x}%</span>
|
|
</div>
|
|
<div className="sticker-prop-row">
|
|
<span className="sticker-prop-label">位置 Y</span>
|
|
<input
|
|
type="range"
|
|
className="sticker-prop-slider"
|
|
min={0}
|
|
max={100}
|
|
value={sticker.y}
|
|
onChange={(e) => onUpdate(sticker.id, { y: Number(e.target.value) })}
|
|
/>
|
|
<span className="sticker-prop-value">{sticker.y}%</span>
|
|
</div>
|
|
|
|
{/* 尺寸 */}
|
|
<div className="sticker-prop-row">
|
|
<span className="sticker-prop-label">大小</span>
|
|
<input
|
|
type="range"
|
|
className="sticker-prop-slider"
|
|
min={5}
|
|
max={50}
|
|
value={sticker.width}
|
|
onChange={(e) =>
|
|
onUpdate(sticker.id, {
|
|
width: Number(e.target.value),
|
|
height: Number(e.target.value),
|
|
})
|
|
}
|
|
/>
|
|
<span className="sticker-prop-value">{sticker.width}%</span>
|
|
</div>
|
|
|
|
{/* 旋转 */}
|
|
<div className="sticker-prop-row">
|
|
<span className="sticker-prop-label">旋转</span>
|
|
<input
|
|
type="range"
|
|
className="sticker-prop-slider"
|
|
min={-180}
|
|
max={180}
|
|
value={sticker.rotation}
|
|
onChange={(e) => onUpdate(sticker.id, { rotation: Number(e.target.value) })}
|
|
/>
|
|
<span className="sticker-prop-value">{sticker.rotation}°</span>
|
|
</div>
|
|
|
|
{/* 透明度 */}
|
|
<div className="sticker-prop-row">
|
|
<span className="sticker-prop-label">透明度</span>
|
|
<input
|
|
type="range"
|
|
className="sticker-prop-slider"
|
|
min={0}
|
|
max={100}
|
|
value={sticker.opacity}
|
|
onChange={(e) => onUpdate(sticker.id, { opacity: Number(e.target.value) })}
|
|
/>
|
|
<span className="sticker-prop-value">{sticker.opacity}%</span>
|
|
</div>
|
|
|
|
{/* 时间 */}
|
|
<div className="sticker-prop-row">
|
|
<span className="sticker-prop-label">开始</span>
|
|
<input
|
|
type="number"
|
|
className="sticker-prop-number"
|
|
min={0}
|
|
max={totalDuration}
|
|
step={0.1}
|
|
value={sticker.start_time}
|
|
onChange={(e) => onUpdate(sticker.id, { start_time: Number(e.target.value) })}
|
|
/>
|
|
<span className="sticker-prop-label">时长</span>
|
|
<input
|
|
type="number"
|
|
className="sticker-prop-number"
|
|
min={0}
|
|
max={totalDuration}
|
|
step={0.1}
|
|
value={sticker.duration}
|
|
onChange={(e) => onUpdate(sticker.id, { duration: Number(e.target.value) })}
|
|
/>
|
|
</div>
|
|
|
|
{/* 文字贴纸特有属性 */}
|
|
<TextStickerPropsEditor sticker={sticker} onUpdate={onUpdate} />
|
|
|
|
{/* 预览 */}
|
|
<StickerPreview sticker={sticker} />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default StickerPropsEditor
|