名称:json-canvas 描述:使用节点、边、组和连接创建和编辑 JSON Canvas 文件(.canvas)。当处理 .canvas 文件、创建视觉画布、思维导图、流程图,或当用户在 Obsidian 中提到 Canvas 文件时使用。
JSON Canvas 技能
此技能使技能兼容代理能够创建和编辑在 Obsidian 和其他应用程序中使用的有效 JSON Canvas 文件(.canvas)。
概述
JSON Canvas 是一种用于无限画布数据的开放文件格式。Canvas 文件使用 .canvas 扩展名,并包含遵循 JSON Canvas Spec 1.0 的有效 JSON。
文件结构
一个 canvas 文件包含两个顶级数组:
{
"nodes": [],
"edges": []
}
nodes(可选):节点对象数组edges(可选):连接节点的边对象数组
节点
节点是放置在画布上的对象。有四种节点类型:
text- 带有 Markdown 的文本内容file- 引用文件或附件link- 外部 URLgroup- 其他节点的视觉容器
Z-Index 排序
节点按 z-index 在数组中排序:
- 第一个节点 = 底层(显示在下方)
- 最后一个节点 = 顶层(显示在上方)
通用节点属性
所有节点共享这些属性:
| 属性 | 必需 | 类型 | 描述 |
|---|---|---|---|
id |
是 | 字符串 | 节点的唯一标识符 |
type |
是 | 字符串 | 节点类型:text、file、link 或 group |
x |
是 | 整数 | X 位置(像素) |
y |
是 | 整数 | Y 位置(像素) |
width |
是 | 整数 | 宽度(像素) |
height |
是 | 整数 | 高度(像素) |
color |
否 | canvasColor | 节点颜色(参见颜色部分) |
文本节点
文本节点包含 Markdown 内容。
{
"id": "6f0ad84f44ce9c17",
"type": "text",
"x": 0,
"y": 0,
"width": 400,
"height": 200,
"text": "# Hello World
This is **Markdown** content."
}
| 属性 | 必需 | 类型 | 描述 |
|---|---|---|---|
text |
是 | 字符串 | 带有 Markdown 语法的纯文本 |
文件节点
文件节点引用文件或附件(图像、视频、PDF、笔记等)。
{
"id": "a1b2c3d4e5f67890",
"type": "file",
"x": 500,
"y": 0,
"width": 400,
"height": 300,
"file": "Attachments/diagram.png"
}
{
"id": "b2c3d4e5f6789012",
"type": "file",
"x": 500,
"y": 400,
"width": 400,
"height": 300,
"file": "Notes/Project Overview.md",
"subpath": "#Implementation"
}
| 属性 | 必需 | 类型 | 描述 |
|---|---|---|---|
file |
是 | 字符串 | 系统内的文件路径 |
subpath |
否 | 字符串 | 链接到标题或块(以 # 开头) |
链接节点
链接节点显示外部 URL。
{
"id": "c3d4e5f678901234",
"type": "link",
"x": 1000,
"y": 0,
"width": 400,
"height": 200,
"url": "https://obsidian.md"
}
| 属性 | 必需 | 类型 | 描述 |
|---|---|---|---|
url |
是 | 字符串 | 外部 URL |
组节点
组节点是用于组织其他节点的视觉容器。
{
"id": "d4e5f6789012345a",
"type": "group",
"x": -50,
"y": -50,
"width": 1000,
"height": 600,
"label": "Project Overview",
"color": "4"
}
{
"id": "e5f67890123456ab",
"type": "group",
"x": 0,
"y": 700,
"width": 800,
"height": 500,
"label": "Resources",
"background": "Attachments/background.png",
"backgroundStyle": "cover"
}
| 属性 | 必需 | 类型 | 描述 |
|---|---|---|---|
label |
否 | 字符串 | 组的文本标签 |
background |
否 | 字符串 | 背景图像路径 |
backgroundStyle |
否 | 字符串 | 背景渲染样式 |
背景样式
| 值 | 描述 |
|---|---|
cover |
填充节点的整个宽度和高度 |
ratio |
保持背景图像的宽高比 |
repeat |
在两个方向上重复图像作为图案 |
边
边是连接节点的线。
{
"id": "f67890123456789a",
"fromNode": "6f0ad84f44ce9c17",
"toNode": "a1b2c3d4e5f67890"
}
{
"id": "0123456789abcdef",
"fromNode": "6f0ad84f44ce9c17",
"fromSide": "right",
"fromEnd": "none",
"toNode": "b2c3d4e5f6789012",
"toSide": "left",
"toEnd": "arrow",
"color": "1",
"label": "leads to"
}
| 属性 | 必需 | 类型 | 默认 | 描述 |
|---|---|---|---|---|
id |
是 | 字符串 | - | 边的唯一标识符 |
fromNode |
是 | 字符串 | - | 连接开始的节点 ID |
fromSide |
否 | 字符串 | - | 边开始的侧边 |
fromEnd |
否 | 字符串 | none |
边起点的形状 |
toNode |
是 | 字符串 | - | 连接结束的节点 ID |
toSide |
否 | 字符串 | - | 边结束的侧边 |
toEnd |
否 | 字符串 | arrow |
边终点的形状 |
color |
否 | canvasColor | - | 线条颜色 |
label |
否 | 字符串 | - | 边的文本标签 |
侧边值
| 值 | 描述 |
|---|---|
top |
节点的顶部边缘 |
right |
节点的右侧边缘 |
bottom |
节点的底部边缘 |
left |
节点的左侧边缘 |
端点形状
| 值 | 描述 |
|---|---|
none |
无端点形状 |
arrow |
箭头端点 |
颜色
canvasColor 类型可以通过两种方式指定:
十六进制颜色
{
"color": "#FF0000"
}
预设颜色
{
"color": "1"
}
| 预设 | 颜色 |
|---|---|
"1" |
红色 |
"2" |
橙色 |
"3" |
黄色 |
"4" |
绿色 |
"5" |
青色 |
"6" |
紫色 |
注意:预设颜色的具体值未定义,允许应用程序使用自己的品牌颜色。
完整示例
简单画布带文本和连接
{
"nodes": [
{
"id": "8a9b0c1d2e3f4a5b",
"type": "text",
"x": 0,
"y": 0,
"width": 300,
"height": 150,
"text": "# Main Idea
This is the central concept."
},
{
"id": "1a2b3c4d5e6f7a8b",
"type": "text",
"x": 400,
"y": -100,
"width": 250,
"height": 100,
"text": "## Supporting Point A
Details here."
},
{
"id": "2b3c4d5e6f7a8b9c",
"type": "text",
"x": 400,
"y": 100,
"width": 250,
"height": 100,
"text": "## Supporting Point B
More details."
}
],
"edges": [
{
"id": "3c4d5e6f7a8b9c0d",
"fromNode": "8a9b0c1d2e3f4a5b",
"fromSide": "right",
"toNode": "1a2b3c4d5e6f7a8b",
"toSide": "left"
},
{
"id": "4d5e6f7a8b9c0d1e",
"fromNode": "8a9b0c1d2e3f4a5b",
"fromSide": "right",
"toNode": "2b3c4d5e6f7a8b9c",
"toSide": "left"
}
]
}
项目看板带组
{
"nodes": [
{
"id": "5e6f7a8b9c0d1e2f",
"type": "group",
"x": 0,
"y": 0,
"width": 300,
"height": 500,
"label": "To Do",
"color": "1"
},
{
"id": "6f7a8b9c0d1e2f3a",
"type": "group",
"x": 350,
"y": 0,
"width": 300,
"height": 500,
"label": "In Progress",
"color": "3"
},
{
"id": "7a8b9c0d1e2f3a4b",
"type": "group",
"x": 700,
"y": 0,
"width": 300,
"height": 500,
"label": "Done",
"color": "4"
},
{
"id": "8b9c0d1e2f3a4b5c",
"type": "text",
"x": 20,
"y": 50,
"width": 260,
"height": 80,
"text": "## Task 1
Implement feature X"
},
{
"id": "9c0d1e2f3a4b5c6d",
"type": "text",
"x": 370,
"y": 50,
"width": 260,
"height": 80,
"text": "## Task 2
Review PR #123",
"color": "2"
},
{
"id": "0d1e2f3a4b5c6d7e",
"type": "text",
"x": 720,
"y": 50,
"width": 260,
"height": 80,
"text": "## Task 3
~~Setup CI/CD~~"
}
],
"edges": []
}
研究画布带文件和链接
{
"nodes": [
{
"id": "1e2f3a4b5c6d7e8f",
"type": "text",
"x": 300,
"y": 200,
"width": 400,
"height": 200,
"text": "# Research Topic
## Key Questions
- How does X affect Y?
- What are the implications?",
"color": "5"
},
{
"id": "2f3a4b5c6d7e8f9a",
"type": "file",
"x": 0,
"y": 0,
"width": 250,
"height": 150,
"file": "Literature/Paper A.pdf"
},
{
"id": "3a4b5c6d7e8f9a0b",
"type": "file",
"x": 0,
"y": 200,
"width": 250,
"height": 150,
"file": "Notes/Meeting Notes.md",
"subpath": "#Key Insights"
},
{
"id": "4b5c6d7e8f9a0b1c",
"type": "link",
"x": 0,
"y": 400,
"width": 250,
"height": 100,
"url": "https://example.com/research"
},
{
"id": "5c6d7e8f9a0b1c2d",
"type": "file",
"x": 750,
"y": 150,
"width": 300,
"height": 250,
"file": "Attachments/diagram.png"
}
],
"edges": [
{
"id": "6d7e8f9a0b1c2d3e",
"fromNode": "2f3a4b5c6d7e8f9a",
"fromSide": "right",
"toNode": "1e2f3a4b5c6d7e8f",
"toSide": "left",
"label": "supports"
},
{
"id": "7e8f9a0b1c2d3e4f",
"fromNode": "3a4b5c6d7e8f9a0b",
"fromSide": "right",
"toNode": "1e2f3a4b5c6d7e8f",
"toSide": "left",
"label": "informs"
},
{
"id": "8f9a0b1c2d3e4f5a",
"fromNode": "4b5c6d7e8f9a0b1c",
"fromSide": "right",
"toNode": "1e2f3a4b5c6d7e8f",
"toSide": "left",
"toEnd": "arrow",
"color": "6"
},
{
"id": "9a0b1c2d3e4f5a6b",
"fromNode": "1e2f3a4b5c6d7e8f",
"fromSide": "right",
"toNode": "5c6d7e8f9a0b1c2d",
"toSide": "left",
"label": "visualized by"
}
]
}
流程图
{
"nodes": [
{
"id": "a0b1c2d3e4f5a6b7",
"type": "text",
"x": 200,
"y": 0,
"width": 150,
"height": 60,
"text": "**Start**",
"color": "4"
},
{
"id": "b1c2d3e4f5a6b7c8",
"type": "text",
"x": 200,
"y": 100,
"width": 150,
"height": 60,
"text": "Step 1:
Gather data"
},
{
"id": "c2d3e4f5a6b7c8d9",
"type": "text",
"x": 200,
"y": 200,
"width": 150,
"height": 80,
"text": "**Decision**
Is data valid?",
"color": "3"
},
{
"id": "d3e4f5a6b7c8d9e0",
"type": "text",
"x": 400,
"y": 200,
"width": 150,
"height": 60,
"text": "Process data"
},
{
"id": "e4f5a6b7c8d9e0f1",
"type": "text",
"x": 0,
"y": 200,
"width": 150,
"height": 60,
"text": "Request new data",
"color": "1"
},
{
"id": "f5a6b7c8d9e0f1a2",
"type": "text",
"x": 400,
"y": 320,
"width": 150,
"height": 60,
"text": "**End**",
"color": "4"
}
],
"edges": [
{
"id": "a6b7c8d9e0f1a2b3",
"fromNode": "a0b1c2d3e4f5a6b7",
"fromSide": "bottom",
"toNode": "b1c2d3e4f5a6b7c8",
"toSide": "top"
},
{
"id": "b7c8d9e0f1a2b3c4",
"fromNode": "b1c2d3e4f5a6b7c8",
"fromSide": "bottom",
"toNode": "c2d3e4f5a6b7c8d9",
"toSide": "top"
},
{
"id": "c8d9e0f1a2b3c4d5",
"fromNode": "c2d3e4f5a6b7c8d9",
"fromSide": "right",
"toNode": "d3e4f5a6b7c8d9e0",
"toSide": "left",
"label": "Yes",
"color": "4"
},
{
"id": "d9e0f1a2b3c4d5e6",
"fromNode": "c2d3e4f5a6b7c8d9",
"fromSide": "left",
"toNode": "e4f5a6b7c8d9e0f1",
"toSide": "right",
"label": "No",
"color": "1"
},
{
"id": "e0f1a2b3c4d5e6f7",
"fromNode": "e4f5a6b7c8d9e0f1",
"fromSide": "top",
"fromEnd": "none",
"toNode": "b1c2d3e4f5a6b7c8",
"toSide": "left",
"toEnd": "arrow"
},
{
"id": "f1a2b3c4d5e6f7a8",
"fromNode": "d3e4f5a6b7c8d9e0",
"fromSide": "bottom",
"toNode": "f5a6b7c8d9e0f1a2",
"toSide": "top"
}
]
}
ID 生成
节点和边的 ID 必须是唯一的字符串。Obsidian 生成 16 个字符的十六进制 ID:
"id": "6f0ad84f44ce9c17"
"id": "a3b2c1d0e9f8g7h6"
"id": "1234567890abcdef"
此格式是 16 个字符的小写十六进制字符串(64 位随机值)。
布局指南
定位
- 坐标可以为负(画布无限延伸)
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"或有效的十六进制颜色