好久没用D3库作可视化了,现在主要是用百度的echarts库,在项目中做简单的图表太方便了。但像是做关系图其实用echarts也很方便,这次用D3实现主要是复习一下以前做的东西,顺便记录一下。
以下是我参考到的实例代码:
D3官方图实例参考echarts做关系图实例参考我们先通过Cypher查询将数据从Neo4j中查询出来,Neo4j构建和查询可以参考我上篇博客 基于Neo4j的外贸企业关系图谱做企业相似度查询
由于原Cypher语句比较长,通过下面的查询导出的格式也是一样的,根据自己的关系查询进行修改即可:
MATCH p=(n:Enterprise)-[]->() RETURN p limit 20查询后的结果如下,点击右上角下载图标,导出为JSON格式
可以进入JSON在线解析,查看导出的JSON格式:
新建好一个Web项目后,先把D3的JS库导入进来,再通过d3.json()来读取我们的json文件。
可以通过本地方式导入
<!-- 增加D3元素库 --> <script src="js/d3.v4.min.js"></script>如果不想下到本地,也可以通过CDN方式直接导入
<!-- 增加D3元素库 --> <script src="https://cdn.bootcdn.net/ajax/libs/d3/4.9.1/d3.min.js"></script>导入D3后,就可以通过d3.json方法读取本地的json文件:
var graph; //d3.json获取数据 d3.json("data/records.json", function(error, data) { if(error) throw error; graph = data; console.log(graph[0].p); }先运行结果,查看控制台打印的结果如下: `
还是先去D3官方图实例参考分析一下标准数据格式,从下图可以看到 data 分为 nodes 和 links 两部分,因为在D3中节点和关系是分开渲染的,渲染过后会自动在各个部分内生成位置坐标的属性。 此时我们需要将neo4j导出的数据做标准化,使数据格式符合D3标准。 (需要注意一个坑:要对json数据做去重处理,不然D3在渲染时无法将节点关系弄出来,原理其实就是节点的唯一标识产生了冲突,我们要保证节点的唯一性) 以下是标准化的代码,将json数据分离到nodes和links两部分,为数据绑定打好基础:
// 图数据 var graph; let nodes =[]; let links = []; // 存放节点和关系 let nodeSet = []; // 存放去重后nodes的id //d3.json获取数据 d3.json("data/records.json", function(error, data) { if(error) throw error; graph = data; console.log(graph[0].p); for (let item of graph) { // console.log(item.p.start instanceof Array) // console.log(item.p) // 重新更改data格式 if(nodeSet.indexOf(item.p.start.identity) == -1){ nodeSet.push(item.p.start.identity) nodes.push({ id: item.p.start.identity, label: item.p.start.labels[0], properties: item.p.start.properties }) } if(nodeSet.indexOf(item.p.end.identity) == -1){ nodeSet.push(item.p.end.identity) nodes.push({ id: item.p.end.identity, label: item.p.end.labels[0], properties: item.p.end.properties }) } links.push({ source: item.p.segments[0].relationship.start, target: item.p.segments[0].relationship.end, type: item.p.segments[0].relationship.type, properties: item.p.segments[0].relationship.properties }) } console.log(nodes) console.log(links) }数据处理好之后,只需要把数据绑定到D3上即可,至于展示部分官网参考代码已经有了,在此不再做详细展开,后面也可以参考我的代码注释理解。
最终展示出的效果如下:
从二图中可以看到可视化还做了一些事件处理,目前完成了拖拽事件、鼠标进入、鼠标离开三个事件。当鼠标放到节点上时,在右边会展示节点信息,并隐藏与该节点无关的其他节点。
最后,加了个节点文字切换和搜索功能,之前的节点全挨在一起,于是又加了个碰撞检测模型,最终效果如下:
像这种力导向关系图可以结合多个力学模型自行扩充,其他的效果可以自行拓展:(官方参考的力模型)
Centering(向心力)Collision(碰撞检测)Links(弹簧力)Many-Body(电荷力)Positioning(定位力)个人实现代码(仅供参考): github地址:https://github.com/CoderWanp/neo4j-d3-graph
直接看页面效果: Demo展示:https://coderwanp.github.io/neo4j-d3-graph/