fix(canvas): 画布视觉 - 收敛边框与网格样式

This commit is contained in:
ddCat
2026-08-22 13:09:34 +08:00
parent 772e7bbef7
commit 227e548503
5 changed files with 12 additions and 13 deletions

View File

@@ -394,7 +394,7 @@ export function CanvasNodePromptPanel({ node, isRunning, onPromptChange, onConfi
setExpandedPromptOpen(false);
}}
styles={{
container: { border: `1px solid ${theme.node.edge}`, borderRadius: "var(--canvas-composer-radius)", padding: 0, overflow: "hidden", background: theme.node.panel, boxShadow: theme.node.shadow },
container: { border: 0, borderRadius: "var(--canvas-composer-radius)", padding: 0, overflow: "hidden", background: theme.node.panel, boxShadow: theme.node.shadow },
body: { minHeight: 0, padding: 0 },
}}
>

View File

@@ -110,6 +110,7 @@ export const CanvasNode = React.memo(function CanvasNode({
const hasImageContent = data.type === CanvasNodeType.Image && Boolean(data.metadata?.content);
const hasVideoContent = data.type === CanvasNodeType.Video && Boolean(data.metadata?.content);
const hasAudioContent = data.type === CanvasNodeType.Audio && Boolean(data.metadata?.content);
const isComposerNode = data.type === CanvasNodeType.Config;
const hasMediaContent = hasImageContent || hasVideoContent || hasAudioContent;
const hasReplaceAction = !readOnly && (data.type === CanvasNodeType.Image || data.type === CanvasNodeType.Video);
const isBatchRoot = data.type === CanvasNodeType.Image && Boolean(data.metadata?.isBatchRoot) && batchCount > 1;
@@ -292,8 +293,8 @@ export const CanvasNode = React.memo(function CanvasNode({
data-state={data.metadata?.status || (isActive ? "active" : isRelated ? "related" : "idle")}
style={{
background: hasImageContent || hasVideoContent ? "transparent" : theme.node.fill,
border: `1px solid ${theme.node.edge}`,
boxShadow: isSelected ? `0 0 0 2px ${theme.node.activeStroke}, ${theme.node.hoverShadow}` : hovered ? theme.node.hoverShadow : theme.node.shadow,
border: isComposerNode || isSelected ? "0" : `1px solid ${theme.node.edge}`,
boxShadow: isComposerNode ? "none" : isSelected || hovered ? theme.node.hoverShadow : theme.node.shadow,
}}
onMouseDown={(event) => onMouseDown(event, data.id)}
onDoubleClick={(event) => {
@@ -636,12 +637,10 @@ function NodeExternalHeader({ node, scale, active, editable, editing, draft, the
className="canvas-node-external-header absolute bottom-full left-0 z-[var(--node-z-overlay)] flex h-6 items-center gap-1 overflow-hidden"
style={{
maxWidth: maxHeaderWidth,
border: `1px solid ${theme.node.edge}`,
borderRadius: "var(--r-sm)",
background: theme.node.panel,
paddingInline: "var(--space-1-half)",
color: active ? theme.node.text : theme.node.label,
boxShadow: active ? theme.node.shadow : undefined,
transform: `scale(var(--canvas-live-inverse-scale, ${inverseScale}))`,
transformOrigin: "left bottom",
}}
@@ -653,8 +652,8 @@ function NodeExternalHeader({ node, scale, active, editable, editing, draft, the
<input
autoFocus
value={draft}
className="h-6 min-w-20 max-w-[190px] flex-1 truncate rounded border bg-transparent px-1.5 text-xs font-medium outline-none"
style={{ background: theme.spatial.elevated, borderColor: theme.toolbar.border, color: theme.node.text, boxShadow: "var(--elevation-card)" }}
className="h-6 min-w-20 max-w-[190px] flex-1 truncate rounded bg-transparent px-1.5 text-xs font-medium outline-none"
style={{ background: theme.spatial.elevated, color: theme.node.text }}
onChange={(event) => onDraftChange(event.target.value)}
onFocus={(event) => event.currentTarget.select()}
onBlur={onCommit}
@@ -665,7 +664,7 @@ function NodeExternalHeader({ node, scale, active, editable, editing, draft, the
aria-label="节点名称"
/>
) : editable ? (
<button type="button" className="group flex min-w-0 flex-1 items-center gap-1 rounded px-0.5 text-xs font-medium outline-none transition-opacity hover:opacity-100 focus-visible:ring-1" style={{ opacity: active ? 1 : 0.78, "--tw-ring-color": theme.node.activeStroke } as React.CSSProperties} onClick={onEdit} aria-label={`编辑节点名称:${node.title}`}>
<button type="button" className="group flex min-w-0 flex-1 items-center gap-1 rounded px-0.5 text-xs font-medium outline-none transition-opacity hover:opacity-100 focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-1" style={{ opacity: active ? 1 : 0.78, outlineColor: theme.node.muted }} onClick={onEdit} aria-label={`编辑节点名称:${node.title}`}>
<span className="min-w-0 flex-1 truncate" title={node.title}>{node.title}</span>
<Pencil className="size-2.5 shrink-0 opacity-55 transition-opacity group-hover:opacity-100" />
</button>

View File

@@ -426,7 +426,7 @@ function CanvasGrid({ mode }: { mode: CanvasBackgroundMode }) {
backgroundImage,
backgroundSize: "var(--canvas-grid-size) var(--canvas-grid-size)",
transform: "translate3d(var(--canvas-grid-x), var(--canvas-grid-y), 0)",
opacity: 0.55,
opacity: 0.42,
willChange: "transform",
}}
/>

View File

@@ -70,9 +70,9 @@ export const canvasThemes = {
},
dark: {
canvas: {
background: "#090a0c",
dot: "rgba(174,184,199,.32)",
line: "rgba(174,184,199,.16)",
background: "#0b0b0b",
dot: "rgba(170,170,170,.22)",
line: "rgba(170,170,170,.10)",
selectionFill: "rgba(255,255,255,.12)",
},
node: {

View File

@@ -7,7 +7,7 @@ export const CANVAS_SELECTION_PREVIEW_EVENT = "canvas:selection-preview";
// 空间网格点模式的点半径(像素单位)。远距(缩放 < 0.12)时用更小半径避免糊成一团。
// 同时被 <CanvasGrid>(infinite-canvas)与滚动同步(applyCanvasLiveViewport)共享,避免两处漂移。
export function canvasDotPx(scale: number): string {
return scale < 0.12 ? "1.2px" : "2px";
return scale < 0.12 ? "0.8px" : "1.25px";
}
export function applyCanvasLiveViewport(container: HTMLDivElement | null, viewport: ViewportTransform, notify = true) {