feat: 优化画布图片选中工具栏
1. 选中图片时在顶部显示工具栏(放大、移除背景、场景、角度、扩展、调整) 2. 工具栏使用圆角胶囊样式,类似竞品设计 3. 显示图片标题和尺寸信息 4. 添加更多操作下拉菜单(下载、删除) Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
049795e264
commit
8f1f924421
@ -247,8 +247,8 @@ export function CanvasWorkspace() {
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 节点层 - 使用虚拟化渲染 */}
|
||||
<div className="absolute inset-0">
|
||||
{/* 节点层 - 使用虚拟化渲染,允许工具栏溢出 */}
|
||||
<div className="absolute inset-0" style={{ overflow: 'visible' }}>
|
||||
{visibleNodes.map(renderNode)}
|
||||
</div>
|
||||
|
||||
|
||||
@ -322,10 +322,21 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) {
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* 选中时在图片上方显示标题和尺寸 */}
|
||||
{isSelected && data.src && (
|
||||
<div className="absolute -top-7 left-0 right-0 flex items-center justify-between text-xs text-muted-foreground px-1">
|
||||
<div className="flex items-center gap-1">
|
||||
<ImagePlus className="h-3 w-3" />
|
||||
<span className="truncate max-w-[150px]">{data.prompt || '图片'}</span>
|
||||
</div>
|
||||
<span>{node.size.width} × {node.size.height}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div
|
||||
className={cn(
|
||||
"relative w-full h-full bg-card rounded-lg overflow-hidden border shadow-sm",
|
||||
isSelected && "border-primary"
|
||||
"relative w-full h-full bg-card rounded-lg overflow-hidden border-2 shadow-sm transition-colors",
|
||||
isSelected ? "border-primary" : "border-transparent"
|
||||
)}
|
||||
onMouseEnter={() => setIsHovered(true)}
|
||||
onMouseLeave={() => setIsHovered(false)}
|
||||
@ -381,91 +392,115 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 选中时显示的顶部工具栏 - 和聊天窗口中的功能一致 */}
|
||||
{/* 选中时显示的顶部工具栏 - 放在图片内部顶部,避免被裁剪 */}
|
||||
{isSelected && data.src && !isProcessing && (
|
||||
<div
|
||||
className="absolute -top-12 left-1/2 -translate-x-1/2 flex items-center gap-1 bg-background/95 backdrop-blur-sm border rounded-lg shadow-lg p-1.5 z-10"
|
||||
className="absolute top-2 left-1/2 -translate-x-1/2 flex items-center gap-0.5 bg-white/95 backdrop-blur-sm border border-gray-200 rounded-full shadow-xl px-2 py-1.5 z-50"
|
||||
style={{
|
||||
pointerEvents: 'auto',
|
||||
minWidth: 'max-content',
|
||||
}}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{/* 放大/高清 */}
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-8 px-2 text-xs gap-1"
|
||||
onClick={() => handleAction('rmbg')}
|
||||
title="抠图"
|
||||
>
|
||||
<Scissors className="h-3.5 w-3.5" />
|
||||
<span className="hidden sm:inline">抠图</span>
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-8 px-2 text-xs gap-1"
|
||||
className="h-9 px-3 text-xs gap-1.5 rounded-full hover:bg-gray-100"
|
||||
onClick={() => handleAction('enhance')}
|
||||
title="变清晰"
|
||||
title="高清放大"
|
||||
>
|
||||
<Sparkles className="h-3.5 w-3.5" />
|
||||
<span className="hidden sm:inline">变清晰</span>
|
||||
<span className="text-[10px] font-medium text-gray-500 border border-gray-300 rounded px-1">HD</span>
|
||||
<span>放大</span>
|
||||
</Button>
|
||||
|
||||
{/* 移除背景/抠图 */}
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-8 px-2 text-xs gap-1"
|
||||
onClick={() => handleAction('extend')}
|
||||
title="扩展"
|
||||
className="h-9 px-3 text-xs gap-1.5 rounded-full hover:bg-gray-100"
|
||||
onClick={() => handleAction('rmbg')}
|
||||
title="移除背景"
|
||||
>
|
||||
<Expand className="h-3.5 w-3.5" />
|
||||
<span className="hidden sm:inline">扩展</span>
|
||||
<Scissors className="h-4 w-4" />
|
||||
<span>移除背景</span>
|
||||
</Button>
|
||||
|
||||
{/* 场景融合 */}
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-8 px-2 text-xs gap-1"
|
||||
onClick={() => handleAction('resize')}
|
||||
title="调整"
|
||||
>
|
||||
<Maximize2 className="h-3.5 w-3.5" />
|
||||
<span className="hidden sm:inline">调整</span>
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-8 px-2 text-xs gap-1"
|
||||
onClick={() => handleAction('angle')}
|
||||
title="角度"
|
||||
>
|
||||
<Move3D className="h-3.5 w-3.5" />
|
||||
<span className="hidden sm:inline">角度</span>
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-8 px-2 text-xs gap-1"
|
||||
className="h-9 px-3 text-xs gap-1.5 rounded-full hover:bg-gray-100"
|
||||
onClick={() => handleAction('scene-fusion')}
|
||||
title="场景"
|
||||
title="场景融合"
|
||||
>
|
||||
<Layers className="h-3.5 w-3.5" />
|
||||
<span className="hidden sm:inline">场景</span>
|
||||
<Layers className="h-4 w-4" />
|
||||
<span>场景</span>
|
||||
</Button>
|
||||
<div className="w-px h-5 bg-border mx-0.5" />
|
||||
|
||||
{/* 角度编辑 */}
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-8 px-2 text-xs gap-1"
|
||||
onClick={handleDownload}
|
||||
title="下载"
|
||||
className="h-9 px-3 text-xs gap-1.5 rounded-full hover:bg-gray-100"
|
||||
onClick={() => handleAction('angle')}
|
||||
title="角度编辑"
|
||||
>
|
||||
<Download className="h-3.5 w-3.5" />
|
||||
<Move3D className="h-4 w-4" />
|
||||
<span>角度</span>
|
||||
</Button>
|
||||
|
||||
{/* 扩展 */}
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-8 px-2 text-xs gap-1 text-destructive hover:text-destructive"
|
||||
onClick={() => deleteNode(node.id)}
|
||||
title="删除"
|
||||
className="h-9 px-3 text-xs gap-1.5 rounded-full hover:bg-gray-100"
|
||||
onClick={() => handleAction('extend')}
|
||||
title="图片扩展"
|
||||
>
|
||||
<Trash2 className="h-3.5 w-3.5" />
|
||||
<Expand className="h-4 w-4" />
|
||||
<span>扩展</span>
|
||||
</Button>
|
||||
|
||||
{/* 尺寸调整 */}
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-9 px-3 text-xs gap-1.5 rounded-full hover:bg-gray-100"
|
||||
onClick={() => handleAction('resize')}
|
||||
title="尺寸调整"
|
||||
>
|
||||
<Maximize2 className="h-4 w-4" />
|
||||
<span>调整</span>
|
||||
</Button>
|
||||
|
||||
{/* 更多操作 */}
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-9 px-2 rounded-full hover:bg-gray-100"
|
||||
title="更多"
|
||||
>
|
||||
<MoreVertical className="h-4 w-4" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuItem onClick={handleDownload}>
|
||||
<Download className="h-4 w-4 mr-2" />
|
||||
下载图片
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem
|
||||
onClick={() => deleteNode(node.id)}
|
||||
className="text-destructive focus:text-destructive"
|
||||
>
|
||||
<Trash2 className="h-4 w-4 mr-2" />
|
||||
删除
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user