diff --git a/plugins/canvas/registry/build.mjs b/plugins/canvas/registry/build.mjs index dc7a92e..cb9befd 100644 --- a/plugins/canvas/registry/build.mjs +++ b/plugins/canvas/registry/build.mjs @@ -16,7 +16,7 @@ const nodeModules = join(root, "node_modules"); // 与插件 src 里 definePlugin({version}) 保持一致,避免清单与产物版本脱节。 const OFFICIAL = [ { id: "markdown", dir: "markdown", name: "Markdown 节点", description: "在画布中编辑与渲染 Markdown", icon: "📝" }, - { id: "svg", dir: "svg", name: "SVG 节点", description: "编辑与渲染 SVG,可接收上游文本节点的 SVG 源码", icon: "🔷" }, + { id: "svg", dir: "svg", name: "SVG 节点", description: "透明背景渲染 SVG,可接收上游文本节点的 SVG 源码", icon: "🔷" }, { id: "html", dir: "html", name: "HTML 节点", description: "沙箱 iframe 渲染 HTML,支持 {{input}} 注入上游文本", icon: "🌐" }, { id: "panorama", dir: "panorama", name: "3D 全景节点", description: "查看 360° 等距柱状全景图,可从上游图片节点取图", icon: "🧭" }, { id: "sticky-note", dir: "sticky-note", name: "便利贴节点", description: "可自选颜色、双击编辑、拖动即可移动的便利贴", icon: "📌" }, diff --git a/plugins/canvas/sdk/src/types.ts b/plugins/canvas/sdk/src/types.ts index 32edf76..ab605bc 100644 --- a/plugins/canvas/sdk/src/types.ts +++ b/plugins/canvas/sdk/src/types.ts @@ -275,6 +275,8 @@ export type CanvasNodeDefinition = { showInCreateMenu?: boolean; // 默认 true hasSourceHandle?: boolean; // 右侧输出连接点,默认 true hidePanel?: boolean; // 为 true 时:点击/新建不弹出下方面板(含内置生图面板),纯展示型节点用 + // 为 true 时:节点卡片背景与边框透明,内容直接融入画布(如 SVG/矢量图);选中时仍显示选中描边 + transparentBackground?: boolean; autoOpenPanel?: boolean; // 为 true 时:单击节点自动打开自定义 Panel(默认仅内置节点单击自动打开) // 复用宿主内置生成面板;与自定义 Panel 二选一(同时提供时优先 Panel) useBuiltinPanel?: CanvasBuiltinPanelConfig; diff --git a/plugins/canvas/svg/package.json b/plugins/canvas/svg/package.json index 8a520cf..5a432f5 100644 --- a/plugins/canvas/svg/package.json +++ b/plugins/canvas/svg/package.json @@ -1,6 +1,6 @@ { "name": "canvas-plugin-svg", - "version": "1.0.0", + "version": "1.1.0", "private": true, "type": "module", "description": "Infinite Canvas SVG 节点插件", diff --git a/plugins/canvas/svg/src/index.tsx b/plugins/canvas/svg/src/index.tsx index 7d12671..b2c5ead 100644 --- a/plugins/canvas/svg/src/index.tsx +++ b/plugins/canvas/svg/src/index.tsx @@ -1,34 +1,75 @@ -// SVG 节点:编辑与渲染 SVG,无自身内容时可取上游文本节点里的 SVG 源码。 -import { definePlugin, useEffect, useState } from "@infinite-canvas/plugin-sdk"; +// SVG 节点:编辑与渲染 SVG,透明背景直接融入画布;无自身内容时可取上游文本节点里的 SVG 源码。 +import { definePlugin, useEffect, useRef, useState } from "@infinite-canvas/plugin-sdk"; import type { CanvasNodeContentProps } from "@infinite-canvas/plugin-sdk"; -const DEFAULT_SVG = ''; - function SvgContent({ ctx }: CanvasNodeContentProps) { const [editing, setEditing] = useState(false); - const stored = ctx.node.metadata?.content; + const rootRef = useRef(null); + + const stored = ctx.node.metadata?.content as string | undefined; const upstream = ctx .getUpstream() .map((node) => node.metadata?.content) - .find((text) => text?.trim().startsWith(" typeof text === "string" && text.trim().startsWith(" { if (stored === undefined && upstream) ctx.updateMetadata({ content: upstream }); }, [ctx, stored, upstream]); + // 点击节点外部时退出编辑。用 pointerdown 的 capture 阶段:宿主画布在 pointerdown 上 + // preventDefault 会抑制 mousedown,capture 又能先于宿主 stopPropagation 触发。 + useEffect(() => { + if (!editing) return; + const onDocDown = (e: PointerEvent) => { + if (rootRef.current && !rootRef.current.contains(e.target as Node)) setEditing(false); + }; + document.addEventListener("pointerdown", onDocDown, true); + return () => document.removeEventListener("pointerdown", onDocDown, true); + }, [editing]); + + // 交互控件上按下时阻止冒泡,避免误触发节点拖动/双击编辑 + const stop = (e: { stopPropagation: () => void }) => e.stopPropagation(); + const toggle = { position: "absolute", right: 8, top: 8, zIndex: 20, width: 32, height: 32, display: "grid", placeItems: "center", borderRadius: 8, border: `1px solid ${ctx.theme.node.stroke}`, background: `${ctx.theme.toolbar.panel}dd`, color: ctx.theme.node.text, cursor: "pointer" } as const; return ( -
e.stopPropagation()} style={{ position: "relative", height: "100%", width: "100%", display: "flex", flexDirection: "column" }}> - {editing ? ( -