D3 二维图表的绘制系列(二十四)力导向图

上一篇: 旭日图 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);
    })
};

大功告成!!!

发布了250 篇原创文章 · 获赞 88 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/zjw_python/article/details/98617650