关于 json-canvas
供 Claude Code 使用的技能,用于创建和编辑 Obsidian 等应用采用的 JSON Canvas(.canvas)文件。它依据 JSON Canvas Spec 1.0 组织节点、连线及布局。
主要功能
- 01创建和编辑 .canvas 文件
- 02支持文本、文件、链接和分组节点
- 03连接节点并设置连线标签
- 04配置颜色与背景样式
- 05遵循 JSON Canvas Spec 1.0
适用场景
- 01制作可视化思维导图
- 02绘制流程图和节点关系
- 03整理项目看板与规划文档
- 04将笔记和链接组织到画布
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ davepoon/ buildwithclaude --skill json-canvas安装后在 Claude Code 中输入/json-canvas确认已加载。
详细介绍
JSON Canvas
这项技能可让 Claude Code 创建和编辑有效的 JSON Canvas 文件(.canvas),供 Obsidian 和其他应用程序使用。
概述
JSON Canvas 是一种开放文件格式,用于表示无限画布数据。画布文件使用 .canvas 扩展名,内容是符合 JSON Canvas Spec 1.0 的有效 JSON。
何时使用这项技能
- 在 Obsidian 中创建或编辑 .canvas 文件
- 构建可视化思维导图或流程图
- 创建项目看板或规划文档
- 通过连接关系以可视化方式整理笔记
- 构建包含链接内容的图表
文件结构
画布文件包含两个顶层数组:
{
"nodes": [],
"edges": []
}
nodes(可选):节点对象数组edges(可选):用于连接节点的边对象数组
节点
节点是放置在画布上的对象。节点有四种类型:
text- 带有 Markdown 内容的文本file- 文件/附件的引用link- 外部 URLgroup- 用于容纳其他节点的可视化容器
Z 轴顺序
第一个节点 = 底层(显示在其他节点下方) 最后一个节点 = 顶层(显示在其他节点上方)
通用节点属性
| 属性 | 必填 | 类型 | 描述 |
|---|---|---|---|
id | 是 | string | 节点的唯一标识符 |
type | 是 | string | 节点类型:text、file、link 或 group |
x | 是 | integer | X 坐标位置,单位为像素 |
y | 是 | integer | Y 坐标位置,单位为像素 |
width | 是 | integer | 宽度,单位为像素 |
height | 是 | integer | 高度,单位为像素 |
color | 否 | canvasColor | 节点颜色(参见颜色部分) |
文本节点
文本节点包含 Markdown 内容。
{
"id": "text1",
"type": "text",
"x": 0,
"y": 0,
"width": 300,
"height": 150,
"text": "# Heading\n\nThis is **markdown** content."
}
文件节点
文件节点引用文件或附件(图片、视频、PDF、笔记等)
| 属性 | 必填 | 类型 | 描述 |
|---|---|---|---|
file | 是 | string | 系统中的文件路径 |
subpath | 否 | string | 指向标题或区块的链接(以 # 开头) |
{
"id": "file1",
"type": "file",
"x": 350,
"y": 0,
"width": 400,
"height": 300,
"file": "Notes/My Note.md",
"subpath": "#Heading"
}
链接节点
链接节点用于显示外部 URL。
{
"id": "link1",
"type": "link",
"x": 0,
"y": 200,
"width": 300,
"height": 150,
"url": "https://example.com"
}
分组节点
分组节点是用于整理其他节点的可视化容器。
| 属性 | 必填 | 类型 | 描述 |
|---|---|---|---|
label | 否 | string | 分组的文本标签 |
background | 否 | string | 背景图片的路径 |
backgroundStyle | 否 | string | 背景渲染样式 |
背景样式
| 值 | 描述 |
|---|---|
cover | 填满节点的整个宽度和高度 |
ratio | 保持背景图片的宽高比 |
repeat | 将图片沿两个方向重复平铺为图案 |
{
"id": "group1",
"type": "group",
"x": -50,
"y": -50,
"width": 800,
"height": 500,
"label": "Project Ideas",
"color": "4"
}
边
边是连接节点的线条。
| 属性 | 必填 | 类型 | 默认值 | 描述 |
|---|---|---|---|---|
id | 是 | string | - | 边的唯一标识符 |
fromNode | 是 | string | - | 连接起点所在的节点 ID |
fromSide | 否 | string | - | 边的起始侧 |
fromEnd | 否 | string | none | 边起点处的形状 |
toNode | 是 | string | - | 连接终点所在的节点 ID |
toSide | 否 | string | - | 边的结束侧 |
toEnd | 否 | string | arrow | 边终点处的形状 |
color | 否 | canvasColor | - | 线条颜色 |
label | 否 | string | - | 边的文本标签 |
侧边值
| 值 | 描述 |
|---|---|
top | 节点的上边 |
right | 节点的右边 |
bottom | 节点的下边 |
left | 节点的左边 |
端点形状
| 值 | 描述 |
|---|---|
none | 无端点形状 |
arrow | 箭头端点 |
{
"id": "edge1",
"fromNode": "text1",
"fromSide": "right",
"toNode": "file1",
"toSide": "left",
"toEnd": "arrow",
"label": "references"
}
颜色
canvasColor 类型支持十六进制颜色和预设选项。
十六进制颜色
{
"color": "#FF0000"
}
预设颜色
| 预设 | 颜色 |
|---|---|
"1" | 红色 |
"2" | 橙色 |
"3" | 黄色 |
"4" | 绿色 |
"5" | 青色 |
"6" | 紫色 |
预设的具体颜色值有意不作定义,以便应用使用自己的品牌颜色。
完整示例
带文本和连接的简易画布
{
"nodes": [
{
"id": "idea1",
"type": "text",
"x": 0,
"y": 0,
"width": 250,
"height": 100,
"text": "# Main Idea\n\nCore concept goes here"
},
{
"id": "idea2",
"type": "text",
"x": 350,
"y": -50,
"width": 200,
"height": 80,
"text": "## Supporting Point 1\n\nDetails..."
},
{
"id": "idea3",
"type": "text",
"x": 350,
"y": 100,
"width": 200,
"height": 80,
"text": "## Supporting Point 2\n\nMore details..."
}
],
"edges": [
{
"id": "e1",
"fromNode": "idea1",
"fromSide": "right",
"toNode": "idea2",
"toSide": "left",
"toEnd": "arrow"
},
{
"id": "e2",
"fromNode": "idea1",
"fromSide": "right",
"toNode": "idea3",
"toSide": "left",
"toEnd": "arrow"
}
]
}
带分组的项目看板
{
"nodes": [
{
"id": "todo-group",
"type": "group",
"x": 0,
"y": 0,
"width": 300,
"height": 400,
"label": "To Do",
"color": "1"
},
{
"id": "progress-group",
"type": "group",
"x": 350,
"y": 0,
"width": 300,
"height": 400,
"label": "In Progress",
"color": "3"
},
{
"id": "done-group",
"type": "group",
"x": 700,
"y": 0,
"width": 300,
"height": 400,
"label": "Done",
"color": "4"
},
{
"id": "task1",
"type": "text",
"x": 20,
"y": 50,
"width": 260,
"height": 80,
"text": "## Task 1\n\nDescription of first task"
},
{
"id": "task2",
"type": "text",
"x": 370,
"y": 50,
"width": 260,
"height": 80,
"text": "## Task 2\n\nCurrently working on this"
},
{
"id": "task3",
"type": "text",
"x": 720,
"y": 50,
"width": 260,
"height": 80,
"text": "## Task 3\n\n~~Completed task~~"
}
],
"edges": []
}
带文件和链接的研究画布
{
"nodes": [
{
"id": "central",
"type": "text",
"x": 200,
"y": 200,
"width": 200,
"height": 100,
"text": "# Research Topic\n\nMain research question",
"color": "6"
},
{
"id": "notes1",
"type": "file",
"x": 0,
"y": 0,
"width": 180,
"height": 150,
"file": "Research/Literature Review.md"
},
{
"id": "notes2",
"type": "file",
"x": 450,
"y": 0,
"width": 180,
"height": 150,
"file": "Research/Methodology.md"
},
{
"id": "source1",
"type": "link",
"x": 0,
"y": 350,
"width": 180,
"height": 100,
"url": "https://scholar.google.com"
},
{
"id": "source2",
"type": "link",
"x": 450,
"y": 350,
"width": 180,
"height": 100,
"url": "https://arxiv.org"
}
],
"edges": [
{
"id": "e1",
"fromNode": "central",
"toNode": "notes1",
"toEnd": "arrow",
"label": "literature"
},
{
"id": "e2",
"fromNode": "central",
"toNode": "notes2",
"toEnd": "arrow",
"label": "methods"
},
{
"id": "e3",
"fromNode": "central",
"toNode": "source1",
"toEnd": "arrow"
},
{
"id": "e4",
"fromNode": "central",
"toNode": "source2",
"toEnd": "arrow"
}
]
}
流程图
{
"nodes": [
{
"id": "start",
"type": "text",
"x": 100,
"y": 0,
"width": 150,
"height": 60,
"text": "**Start**",
"color": "4"
},
{
"id": "decision",
"type": "text",
"x": 75,
"y": 120,
"width": 200,
"height": 80,
"text": "## Decision\n\nIs condition true?",
"color": "3"
},
{
"id": "yes-path",
"type": "text",
"x": -100,
"y": 280,
"width": 150,
"height": 60,
"text": "**Yes Path**\n\nDo action A"
},
{
"id": "no-path",
"type": "text",
"x": 300,
"y": 280,
"width": 150,
"height": 60,
"text": "**No Path**\n\nDo action B"
},
{
"id": "end",
"type": "text",
"x": 100,
"y": 420,
"width": 150,
"height": 60,
"text": "**End**",
"color": "1"
}
],
"edges": [
{
"id": "e1",
"fromNode": "start",
"fromSide": "bottom",
"toNode": "decision",
"toSide": "top",
"toEnd": "arrow"
},
{
"id": "e2",
"fromNode": "decision",
"fromSide": "left",
"toNode": "yes-path",
"toSide": "top",
"toEnd": "arrow",
"label": "Yes"
},
{
"id": "e3",
"fromNode": "decision",
"fromSide": "right",
"toNode": "no-path",
"toSide": "top",
"toEnd": "arrow",
"label": "No"
},
{
"id": "e4",
"fromNode": "yes-path",
"fromSide": "bottom",
"toNode": "end",
"toSide": "left",
"toEnd": "arrow"
},
{
"id": "e5",
"fromNode": "no-path",
"fromSide": "bottom",
"toNode": "end",
"toSide": "right",
"toEnd": "arrow"
}
]
}
ID 生成
节点和边的 ID 必须是唯一字符串。Obsidian 会生成 16 位十六进制 ID。
格式示例:a1b2c3d4e5f67890
布局指南
定位
- 坐标可以为负值(画布无限延伸)
x向右递增y向下递增- 位置指节点的左上角
建议尺寸
| 节点类型 | 建议宽度 | 建议高度 |
|---|---|---|
| 小型文本 | 200-300 | 80-150 |
| 中型文本 | 300-450 | 150-300 |
| 大型文本 | 400-600 | 300-500 |
| 文件预览 | 300-500 | 200-400 |
| 链接预览 | 250-400 | 100-200 |
| 分组 | 不定 | 不定 |
间距
- 在分组内留出 20-50px 的内边距
- 节点之间留出 50-100px 的间距,以便阅读
- 将节点对齐到网格(10 或 20 的倍数),让布局更整洁
验证规则
- 所有
id值在节点和边中必须唯一 fromNode和toNode必须引用现有节点 ID- 每种节点类型都必须包含必填字段
type必须是以下值之一:text、file、link、groupbackgroundStyle必须是以下值之一:cover、ratio、repeatfromSide、toSide必须是以下值之一:top、right、bottom、leftfromEnd、toEnd必须是以下值之一:none、arrow- 颜色预设必须是
"1"到"6",或有效的十六进制颜色值
参考资料
评论
支持 Markdown