
可视化
Skill 文件
Skill
SKILL.md
SKILL.md
| name | cytoscape-graph |
|---|---|
| title | Cytoscape.js 图论可视化 |
| description | 当用户需要在浏览器中可视化并分析复杂节点—边网络,或明确要求 Cytoscape.js 时,使用此 Skill。该库擅长:有向图、无向图、混合图、自环图、多重图、复合图、随机布局图、网格图、环形图、同心圆图、广度优先层级图、CoSE 力导向图、Dagre 层级图、Cola 力导向图、知识图谱、社交网络图、依赖图、网络拓扑图。不要用于只追求超大规模 WebGL 浏览的 Sigma.js 场景、可拖拽连线的流程编辑器或普通统计图表。 |
Cytoscape.js 图论可视化
在单个 HTML 文件中使用 Cytoscape.js 创建交互式图论网络。内置多种布局算法(force-directed、hierarchical、circular 等)和图论分析(最短路径、中心性、社区检测)。
核心依赖 (CDN 内联 script)
html
<script src="https://cdn.jsdmirror.com/npm/cytoscape@3.30.4/dist/cytoscape.min.js"></script>加载后全局可用:cytoscape 函数
HTML 模板
html
<!DOCTYPE html><html lang="zh-CN"><head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Cytoscape.js 网络图</title> <script src="https://cdn.jsdmirror.com/npm/cytoscape@3.30.4/dist/cytoscape.min.js"></script> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; } #cy { width: 100vw; height: 100vh; } </style></head><body> <div id="cy"></div> <script> const cy = cytoscape({ container: document.getElementById('cy'),
elements: [ // 节点 { data: { id: 'a', label: '节点 A' } }, { data: { id: 'b', label: '节点 B' } }, { data: { id: 'c', label: '节点 C' } }, { data: { id: 'd', label: '节点 D' } }, // 边 { data: { source: 'a', target: 'b', label: '关系1' } }, { data: { source: 'b', target: 'c' } }, { data: { source: 'c', target: 'd' } }, { data: { source: 'd', target: 'a' } }, { data: { source: 'a', target: 'c' } }, ],
style: [ { selector: 'node', style: { 'background-color': '#4A90E2', 'label': 'data(label)', 'color': '#333', 'text-valign': 'bottom', 'text-margin-y': 8, 'font-size': '12px', 'width': 40, 'height': 40, } }, { selector: 'edge', style: { 'width': 2, 'line-color': '#ccc', 'target-arrow-color': '#ccc', 'target-arrow-shape': 'triangle', 'curve-style': 'bezier', 'label': 'data(label)', 'font-size': '10px', 'text-rotation': 'autorotate', } }, ],
layout: { name: 'cose', // 力导向布局 animate: true, }, }); </script></body></html>核心 API
初始化
javascript
const cy = cytoscape({ container: document.getElementById('cy'), // DOM 容器 elements: [...], // 节点和边数据 style: [...], // 样式规则 layout: { name: 'cose' }, // 布局算法});数据格式
javascript
elements: [ // 节点 { data: { id: 'n1', label: '名称', weight: 10, group: 'A' } }, // 边 { data: { id: 'e1', source: 'n1', target: 'n2', label: '边标签', weight: 5 } },]动态操作
javascript
// 添加节点cy.add({ data: { id: 'new', label: '新节点' } });
// 添加边cy.add({ data: { source: 'a', target: 'new' } });
// 移除元素cy.getElementById('new').remove();
// 获取所有节点cy.nodes();
// 获取某节点的邻居cy.getElementById('a').neighborhood();布局算法
| 布局名 | 说明 | 适用场景 |
|---|---|---|
cose | 力导向(内置) | 通用网络图 |
breadthfirst | 层次/BFS | 树/DAG |
circle | 环形排列 | 对等节点 |
grid | 网格排列 | 均匀分布 |
concentric | 同心圆 | 中心性排序 |
random | 随机位置 | 调试用 |
javascript
// 切换布局cy.layout({ name: 'breadthfirst', directed: true }).run();
// 力导向布局参数cy.layout({ name: 'cose', idealEdgeLength: 100, nodeRepulsion: 400000, animate: true, animationDuration: 1000,}).run();外部布局插件
html
<!-- dagre 层次布局 --><script src="https://cdn.jsdmirror.com/npm/cytoscape-dagre@2.5.0/cytoscape-dagre.min.js"></script><script src="https://cdn.jsdmirror.com/npm/dagre@0.8.5/dist/dagre.min.js"></script>
<!-- cola 约束布局 --><script src="https://cdn.jsdmirror.com/npm/cytoscape-cola@2.5.1/cytoscape-cola.min.js"></script>javascript
// dagre 层次布局cy.layout({ name: 'dagre', rankDir: 'TB' }).run();样式系统
选择器语法
javascript
style: [ { selector: 'node', style: { ... } }, // 所有节点 { selector: 'edge', style: { ... } }, // 所有边 { selector: 'node[group="A"]', style: { ... } }, // data 属性筛选 { selector: 'node:selected', style: { ... } }, // 选中状态 { selector: '.highlighted', style: { ... } }, // CSS class { selector: 'edge[weight > 5]', style: { ... } }, // 条件筛选]常用节点样式
javascript
{ 'background-color': '#4A90E2', 'border-color': '#2C3E50', 'border-width': 2, 'width': 'data(weight)', // 数据映射 'height': 'data(weight)', 'label': 'data(label)', 'text-valign': 'center', // center | top | bottom 'text-halign': 'center', // center | left | right 'font-size': '12px', 'shape': 'ellipse', // ellipse | rectangle | round-rectangle | diamond | triangle 'opacity': 0.9,}常用边样式
javascript
{ 'width': 2, 'line-color': '#ccc', 'line-style': 'solid', // solid | dashed | dotted 'target-arrow-shape': 'triangle', // triangle | vee | circle | none 'target-arrow-color': '#ccc', 'curve-style': 'bezier', // bezier | straight | taxi | segments 'label': 'data(label)',}交互事件
javascript
// 点击节点cy.on('tap', 'node', (evt) => { const node = evt.target; console.log('点击节点:', node.id(), node.data());});
// 悬停节点cy.on('mouseover', 'node', (evt) => { evt.target.style('background-color', '#E74C3C');});cy.on('mouseout', 'node', (evt) => { evt.target.style('background-color', '#4A90E2');});
// 点击空白区域cy.on('tap', (evt) => { if (evt.target === cy) { console.log('点击了背景'); }});图论分析
javascript
// 最短路径 (Dijkstra)const dijkstra = cy.elements().dijkstra('#a');const pathToD = dijkstra.pathTo(cy.$('#d'));pathToD.style('line-color', 'red');
// 度中心性cy.nodes().forEach(node => { const degree = node.degree(); node.style('width', 20 + degree * 10);});
// BFS 遍历const bfs = cy.elements().bfs({ root: '#a', directed: true });bfs.path.style('background-color', '#2ECC71');
// 连通分量const components = cy.elements().components();console.log('连通分量数:', components.length);
// PageRankconst pr = cy.elements().pageRank();cy.nodes().forEach(node => { node.style('width', 20 + pr.rank(node) * 200);});常见场景示例
高亮邻居
javascript
cy.on('tap', 'node', (evt) => { cy.elements().style('opacity', 0.2); const node = evt.target; const neighborhood = node.closedNeighborhood(); neighborhood.style('opacity', 1);});
cy.on('tap', (evt) => { if (evt.target === cy) { cy.elements().style('opacity', 1); }});按属性着色
javascript
const colorMap = { A: '#4A90E2', B: '#E74C3C', C: '#2ECC71' };cy.nodes().forEach(node => { const group = node.data('group'); node.style('background-color', colorMap[group] || '#999');});导出为图片
javascript
const png = cy.png({ full: true, scale: 2 });// png 是 base64 data URLconst link = document.createElement('a');link.href = png;link.download = 'graph.png';link.click();注意事项
- 容器必须有明确的宽高:
#cy需要 CSS 设置具体尺寸,否则不渲染。 - 节点 id 必须唯一:重复 id 会导致不可预测的行为。
- 边必须引用已存在的节点 id:
source和target对应的节点必须在 elements 中。 - data vs style 分离:
data()存业务数据,style()控制外观,用data(field)做映射。 - 性能:万级节点以上建议使用
hideEdgesOnViewport: true和textureOnViewport: true。 - 布局是异步的:
layout.run()后使用layout.on('layoutstop', cb)监听完成。
Ln 1, Col 1MarkdownSpaces: 2
No errors