D3 二维图表的绘制系列(二十四)力导向图
上一篇: 旭日图 https://blog.csdn.net/zjw_python/article/details/98613674代码结构和初始化画布的Chart对象介绍,请先看 https://blog.csdn.net/zjw_python/article/details/98182540本图完整的源码地址: https://github.com/zjw666/D3_demo/tree/..
上一篇: 旭日图 https://blog.csdn.net/zjw_python/article/details/98613674
下一篇: 中国地图 https://blog.csdn.net/zjw_python/article/details/98847312
代码结构和初始化画布的Chart对象介绍,请先看 https://blog.csdn.net/zjw_python/article/details/98182540
本图完整的源码地址: https://github.com/zjw666/D3_demo/tree/master/src/force/forceLayout
1 图表效果
2 数据
{
"name": "alphabet",
"children": [
{
"name": "a",
"children": [
{
"name": "a1",
"children": [
{"name": "a11", "house": 2},
{
"name": "c22",
"children":[
{
"name" : "c221"
}
]
},
{"name": "a13", "house": 4}
]
}
]
},
{
"name": "b",
"children": [
{
"name": "b1",
"children": [
{
"name": "c22",
"children":[
{
"name" : "c221"
}
]
},
{"name": "b12", "house": 2}
]
},
{
"name": "b2",
"children": [
{
"name": "c22",
"children":[
{
"name" : "c221"
}
]
}
]
}
]
},
{
"name": "c",
"children": [
{
"name": "c1",
"children": [
{
"name": "c22",
"children":[
{
"name" : "c221",
"children": [
{"name" : "c2211"}
]
}
]
},
{
"name": "c22",
"children":[
{
"name" : "c221",
"children": [
{"name" : "c2211"}
]
}
]
}
]
},
{
"name": "c2",
"children": [
{"name": "c21", "house": 2},
{
"name": "c22",
"children":[
{
"name" : "c221",
"children": [
{"name" : "c2211"}
]
}
]
},
{"name": "c23", "house": 2}
]
},
{
"name": "c3",
"children": [
{
"name": "c22",
"children":[
{
"name" : "c221",
"children": [
{"name" : "c2211"}
]
}
]
},
{
"name": "c22",
"children":[
{
"name" : "c221"
}
]
}
]
}
]
}
]
}
3 关键代码
导入数据
d3.json('./data.json').then(function(data){
.....
将数据转换为节点类型,方便之后渲染
/* ----------------------------处理数据------------------------ */
const root = d3.hierarchy(data);
const nodes = root.descendants();
const links = root.links();
运用d3.forceSimulation
建立力模型,并绑定节点和链接
/* ----------------------------建立力模型------------------------ */
const force = d3.forceSimulation()
.velocityDecay(0.8) //速度衰减
.alphaDecay(0) //alpha衰变, 0表示不衰减
.force("charge", d3.forceManyBody()) //节点相互作用力,默认为斥力-30
.force("collision", d3.forceCollide(config.pointSize + 0.2).strength(0.1)) //碰撞
.force("center", d3.forceCenter(chart.getBodyWidth()/2, chart.getBodyHeight()/2)); //定义力模型坐标的中心点
force.nodes(nodes); //绑定节点
force.force("link", d3.forceLink(links).strength(1).distance(20)); //绑定节点间链接
渲染节点,注意当节点个数变化时,要重新绑定节点
/* ----------------------------渲染节点------------------------ */
chart.renderNodes = function(){
const points = chart.body().selectAll('circle')
.data(nodes);
points.enter()
.append('circle')
.attr('r', config.pointSize)
.attr('fill', (d) => chart._colors(d.depth % 10))
.attr('stroke', config.pointStroke);
points.exit()
.transition()
.attr('r', 1e-6)
.on('end', (d) =>{ //删除点,并重新绑定nodes
nodes.splice(nodes.indexOf(d),1);
force.nodes(nodes);
})
.remove();
}
绑定鼠标交互事件,这里添加了拖拽事件
/* ----------------------------绑定鼠标交互事件------------------------ */
chart.addMouseOn = function(){
const drag = d3.drag()
.on("start", (d) => {
d.fx = d.x;
d.fy = d.y;
})
.on("drag", (d) => {
d.fx = d3.event.x;
d.fy = d3.event.y;
})
.on("end", (d) => {
d.fx = null;
d.fy = null;
});
chart.body().selectAll('circle')
.call(drag);
};
添加tick监听事件,实时更新节点和连线位置
/* ----------------------------绑定tick事件------------------------ */
chart.addForceTick = function(){
force.on("tick", function(){
chart.body().selectAll('line')
.attr("x1", (d) => d.source.x)
.attr("y1", (d) => d.source.y)
.attr("x2", (d) => d.target.x)
.attr("y2", (d) => d.target.y);
chart.body().selectAll('circle')
.attr("cx", (d) => d.x)
.attr("cy", (d) => d.y);
})
};
大功告成!!!
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)