Files
Genarrative/src/components/image-editor/ImageCanvasContextMenusView.tsx
T
kdletters d8b935317d 拆分编辑器前端画布视图
抽出素材栏、生成器、舞台工具栏和画布世界视图

补充各拆分视图的聚焦测试

更新 TRACKING.md 记录第三十四阶段验证
2026-06-17 17:48:12 +08:00

320 lines
10 KiB
TypeScript

import { PlatformFloatingMenu, PlatformFloatingMenuItem } from '../common/PlatformFloatingMenu';
import type {
CanvasClipboard,
CanvasContextMenuState,
CanvasLayer,
CanvasViewport,
ImageContextMenuState,
} from './ImageCanvasEditorTypes';
type ImageCanvasContextMenusViewProps = {
viewport: CanvasViewport;
contextMenu: CanvasContextMenuState | null;
canvasClipboard: CanvasClipboard | null;
imageContextMenu: ImageContextMenuState | null;
imageContextMenuLayer: CanvasLayer | null;
contextShouldShowLayer: boolean;
contextShouldUnlockLayer: boolean;
onPasteCanvasClipboard: (canvasPoint?: { x: number; y: number }) => void;
onCopyContextLayers: (options?: { cut?: boolean }) => void;
onDuplicateContextLayers: () => void;
onMoveContextLayers: (mode: 'up' | 'down' | 'top' | 'bottom') => void;
onGroupContextLayers: () => void;
onUngroupContextLayers: () => void;
onToggleContextLayerVisibility: () => void;
onToggleContextLayerLock: () => void;
onFlipContextLayers: (axis: 'x' | 'y') => void;
onExportContextLayer: () => void;
onDeleteContextLayers: () => void;
onDeleteLayerById: (layerId: string | null) => void;
onCloseContextMenu: () => void;
onCloseImageContextMenu: () => void;
onUpdateScaleFromCenter: (nextScale: number) => void;
onFitLayers: () => void;
onOpenQuickEditPanel: (layer: CanvasLayer) => void;
onOpenLayerMetadata: (layer: CanvasLayer) => void;
onOpenCharacterAnimationPanel: (layer: CanvasLayer) => void;
};
export function ImageCanvasContextMenusView({
viewport,
contextMenu,
canvasClipboard,
imageContextMenu,
imageContextMenuLayer,
contextShouldShowLayer,
contextShouldUnlockLayer,
onPasteCanvasClipboard,
onCopyContextLayers,
onDuplicateContextLayers,
onMoveContextLayers,
onGroupContextLayers,
onUngroupContextLayers,
onToggleContextLayerVisibility,
onToggleContextLayerLock,
onFlipContextLayers,
onExportContextLayer,
onDeleteContextLayers,
onDeleteLayerById,
onCloseContextMenu,
onCloseImageContextMenu,
onUpdateScaleFromCenter,
onFitLayers,
onOpenQuickEditPanel,
onOpenLayerMetadata,
onOpenCharacterAnimationPanel,
}: ImageCanvasContextMenusViewProps) {
return (
<>
{contextMenu ? (
<div
className="image-canvas-editor__context-menu"
role="menu"
aria-label={
contextMenu.kind === 'blank' ? '画布右键菜单' : '图片功能面板'
}
style={{
left: contextMenu.x,
top: contextMenu.y,
}}
onContextMenu={(event) => event.preventDefault()}
onPointerDown={(event) => event.stopPropagation()}
>
{contextMenu.kind === 'blank' ? (
<>
<button
type="button"
role="menuitem"
disabled={!canvasClipboard?.layers.length}
onClick={() => onPasteCanvasClipboard(contextMenu.canvasPoint)}
>
粘贴
</button>
<button
type="button"
role="menuitem"
onClick={() => {
onUpdateScaleFromCenter(viewport.scale * 1.16);
onCloseContextMenu();
}}
>
放大
</button>
<button
type="button"
role="menuitem"
onClick={() => {
onUpdateScaleFromCenter(viewport.scale * 0.86);
onCloseContextMenu();
}}
>
缩小
</button>
<button
type="button"
role="menuitem"
onClick={() => {
onFitLayers();
onCloseContextMenu();
}}
>
显示画布所有元素
</button>
</>
) : (
<>
<button
type="button"
role="menuitem"
onClick={() => onCopyContextLayers()}
>
复制
</button>
<button
type="button"
role="menuitem"
onClick={() => onCopyContextLayers({ cut: true })}
>
剪切
</button>
<button
type="button"
role="menuitem"
disabled={!canvasClipboard?.layers.length}
onClick={() => onPasteCanvasClipboard(contextMenu.canvasPoint)}
>
粘贴
</button>
<button
type="button"
role="menuitem"
onClick={onDuplicateContextLayers}
>
创建副本
</button>
<hr />
<button
type="button"
role="menuitem"
onClick={() => onMoveContextLayers('up')}
>
上移一层
</button>
<button
type="button"
role="menuitem"
onClick={() => onMoveContextLayers('down')}
>
下移一层
</button>
<button
type="button"
role="menuitem"
onClick={() => onMoveContextLayers('top')}
>
置于顶层
</button>
<button
type="button"
role="menuitem"
onClick={() => onMoveContextLayers('bottom')}
>
移动至底层
</button>
<hr />
<button type="button" role="menuitem" onClick={onGroupContextLayers}>
创建组
</button>
<button
type="button"
role="menuitem"
onClick={onUngroupContextLayers}
>
解除组
</button>
<button
type="button"
role="menuitem"
onClick={onToggleContextLayerVisibility}
>
{contextShouldShowLayer ? '显示' : '隐藏'}
</button>
<button
type="button"
role="menuitem"
onClick={onToggleContextLayerLock}
>
{contextShouldUnlockLayer ? '解锁' : '锁定'}
</button>
<hr />
<button
type="button"
role="menuitem"
onClick={() => onFlipContextLayers('x')}
>
水平翻转
</button>
<button
type="button"
role="menuitem"
onClick={() => onFlipContextLayers('y')}
>
垂直翻转
</button>
<button type="button" role="menuitem" onClick={onExportContextLayer}>
导出为
</button>
<hr />
{imageContextMenuLayer ? (
<>
<button
type="button"
role="menuitem"
onClick={() => onOpenQuickEditPanel(imageContextMenuLayer)}
>
快速编辑
</button>
<button
type="button"
role="menuitem"
onClick={() => {
onOpenLayerMetadata(imageContextMenuLayer);
onCloseContextMenu();
onCloseImageContextMenu();
}}
>
查看图片信息
</button>
{imageContextMenuLayer.assetKind === 'character' ? (
<button
type="button"
role="menuitem"
onClick={() =>
onOpenCharacterAnimationPanel(imageContextMenuLayer)
}
>
生成动画
</button>
) : null}
<hr />
</>
) : null}
<button
type="button"
role="menuitem"
className="image-canvas-editor__context-menu-danger"
onClick={onDeleteContextLayers}
>
删除
</button>
</>
)}
</div>
) : null}
{imageContextMenu && imageContextMenuLayer && !contextMenu ? (
<div
className="image-canvas-editor__context-menu"
style={{
left: imageContextMenu.x,
top: imageContextMenu.y,
}}
onPointerDown={(event) => event.stopPropagation()}
>
<PlatformFloatingMenu label="图片功能面板" placement="bottom-start">
<PlatformFloatingMenuItem
className="image-canvas-editor__context-menu-item"
onClick={() => onOpenQuickEditPanel(imageContextMenuLayer)}
>
快速编辑
</PlatformFloatingMenuItem>
<PlatformFloatingMenuItem
className="image-canvas-editor__context-menu-item"
onClick={() => {
onOpenLayerMetadata(imageContextMenuLayer);
onCloseImageContextMenu();
}}
>
查看图片信息
</PlatformFloatingMenuItem>
{imageContextMenuLayer.assetKind === 'character' ? (
<PlatformFloatingMenuItem
className="image-canvas-editor__context-menu-item"
onClick={() => onOpenCharacterAnimationPanel(imageContextMenuLayer)}
>
生成动画
</PlatformFloatingMenuItem>
) : null}
<PlatformFloatingMenuItem
className="image-canvas-editor__context-menu-item"
onClick={() => onDeleteLayerById(imageContextMenuLayer.id)}
>
删除图片
</PlatformFloatingMenuItem>
</PlatformFloatingMenu>
</div>
) : null}
</>
);
}