当前位置:   article > 正文

利用Javascript框架——D3.js制作力导向关系图普_d3.jsv7版本实现力导向图鼠标悬停节点上时所关联的关系变色

d3.jsv7版本实现力导向图鼠标悬停节点上时所关联的关系变色

因公司业务需求,整理制作了一个实用且酷炫力导向关系图。下面是我自己的一个demo。先Po一下成品图(自己做的数据偏少):

图1:
这里写图片描述

1)、引入D3框架,这里引入的版本是v3.0

图2:
这里写图片描述

2)、数据整理(数据结构如下图)

图3:

这里写图片描述

图3:

这里写图片描述

数据解析:数据准备是很重要的一部分。Jstr由两个部分组成:‘nodes’、‘links’,主要数据为‘nodes’,‘links’表示数据之间的联系。‘nodes’部分每条数据由‘name’、‘group’、‘index’组成,可大致理解为按‘group’分组(图一中橘黄色的圆圈为一组、紫色的为一组、蓝色的为一组),‘index’表示此数据的唯一标识。‘links’部分每条数据由‘source’、‘target’组成,‘source’表示源头,‘target’表示指向的目标。如图1中‘中国’指向‘四川’这条线,中国为源头,所以source’为‘nodes’中‘中国’的index即0,target为‘四川’的的index,即3。

3)下面附上代码并做详细讲解

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>D3制作力导向关系图</title>
</head>
<body>
<div class="container" id="main_2"></div>
<script type='text/javascript' src='js/jquery-3.1.1.min.js'></script>
<script src="js/d3.v3.min.js"></script>
<script type="text/javascript">
    var index = 0;
    var width = 1140, height = 1000;
    var color = ["#FF8000", "#9393FF", "#0080FF"];
    var force = d3.layout.force()/*layout将json格式转化为力学图可用的格式*/
            .linkDistance(80)/*指定结点连接线的距离,默认为20*/
            .charge(-600)/*顶点的电荷数。该参数决定是排斥还是吸引,数值越小越互相排斥*/
            .size([width, height]);/*作用域*/
    var svg;
    $(document).ready(function () {
        var jstr = {
            "nodes": [
                {"name": "中国", "group": 1, "index": 0},
                {"name": "内蒙古", "group": 2, "index": 1},
                {"name": "猫咪", "group": 3, "index": 2},
                {"name": "四川", "group": 2, "index": 3},
                {"name": "棕熊", "group": 2, "index": 4},
                {"name": "臭豆腐", "group": 3, "index": 5},
                {"name": "小猪猪", "group": 2, "index": 6},
                {"name": "湖南", "group": 2, "index": 7},
                {"name": "大熊猫", "group": 3, "index": 8},
                {"name": "北京", "group": 2, "index": 9},
                {"name": "雾霾", "group": 3, "index": 10}
            ],
            "links": [{"source": 0, "target": 1},
                {"source": 1, "target": 2},
                {"source": 0, "target": 3},
                {"source": 3, "target": 8},
                {"source": 0, "target": 4},
                {"source": 0, "target": 6},
                {"source": 0, "target": 7},
                {"source": 7, "target": 5},
                {"source": 0, "target": 9},
                {"source": 9, "target": 10},
                {"source": 4, "target": 5}
            ]
        };
        $("#main_2").html(conduct(jstr));/*在$(“#main_2”)作用域内画图*/
    });
    function conduct(graph, link) {
        var dd = $('<div class="d3strench" id="d3strench"></div>');
        $("#main_2").append(dd);
        /*D3采用SVG来更加生动展现数据,此处设置svg的基本样式*/
        svg = d3.select(".d3strench").append("svg")
                .attr("width", 1140)
                .attr("height", height)
                .attr('border', 'red')
                .style({
                    'margin': '0 auto',
                    'display': 'block'
                });
        var nodes = graph.nodes.slice(), /*nodes() 里传入顶点的数组*/
                links = [],
                bilinks = [];
        /*将数据组装成source-->target的形式*/
        graph.links.forEach(function (link) {
            var s = nodes[link.source],
                    t = nodes[link.target],
                    i = {}; // 中间节点
            nodes.push(i);
            links.push({source: s, target: i}, {source: i, target: t});
            bilinks.push([s, i, t]);
        });
//nodes(图5)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74

图5:

这里写图片描述

//links(图6)
  • 1

图6:

这里写图片描述

//blinks(图7)
  • 1

图7:

这里写图片描述

 force.nodes(nodes)
                .links(links)
                .start();
/*svg的path标签被称为”可以组成任何形状的形状”,所以此处用path标签来绘制线条*/
        var link = svg.selectAll(".link")//线条
                .data(bilinks)
                .enter().append("path")
                .attr("class", "link")
                .attr("stroke", function (d) {
                    return color[d[0].group - 1];
                })
                .attr("stroke-width", 1)
/*接下来是数据的渲染*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

图8:

这里写图片描述

图9(一个g标签包裹的内容将被渲染成一个圆圈组):

这里写图片描述

 var node = svg.selectAll(".node")
                .data(graph.nodes)
                .enter().append("g")
                .attr("class", "node")
                .attr("group", function (d) {
                    return d.group;
                })
                .call(force.drag);
        node.append("circle")
                .attr("r", 8)
                .style("fill", function (d) {
                    return color[d.group - 1];
                })
                .style("stroke", function (d) {
                    return color[d.group - 1];
                })
                .style("stroke-width", "8") //圆外面的轮廓线
                .style("stroke-opacity", "0.6"); //圆外面的轮廓线的透明度
        node.filter(function (d) {
            return d.group !== 0;
        })
                .append("text")
                .attr("font-family", "微软雅黑")
                .attr("text-anchor", "middle")
                .attr("dy", function () {   //dy表示文字的偏移量
                    return "0em";
                })
                .attr('x', function (d) {
                    d3.select(this).append('tspan')//添加文字
                            .text(function () {
                                return d.name;
                            });
                    d3.selectAll(".node[group='3'] text")//设置圆圈的样式以及半径
                            .selectAll("tspan")
                            .attr("fill", "#000");
                    d3.selectAll(".node[group='1'] circle")
                            .attr('r', 40)
                            .style('cursor', 'pointer');
                    d3.selectAll(".node[group='2'] circle")
                            .attr('r', 25);
                    d3.selectAll(".node[group='3'] circle")
                            .attr('r', 30);
                });
        node.append("title")//为每个节点设置title(类似于html标签的title属性)
                .text(function (d) {
                    return d.name;
                });
        /*拖拽事件*/
        force.on("tick", function () {
            link.attr("d", function (d) {//设置线条的偏移以及路径
                var dx = d[2].x - d[0].x,
                        dy = d[2].y - d[0].y,
                        dr = Math.sqrt(dx * dx + dy * dy);
                /*下面表示位置的菜蔬中, M(表示画笔落下的位置), A(画椭圆)是大写的,表示绝对位置。当使用相对位置时,要小写*/
                return "M" + d[0].x + "," + d[0].y + "A" + dr + "," + dr + " 0 0,0 " + d[2].x + "," + d[2].y;
            }).attr("fill", "transparent");
            node.attr("transform", function (d) {//circle节点的偏移量
                return "translate(" + d.x + "," + d.y + ")";
            });
        });
        force.stop();
        force.start();
    }
</script>
</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66

D3.js作为数据可视的一个库,可将数据生动化,但相对于echart等来说,难度稍大稍复杂。上面的案例也是在网上搜罗了很多知识点才绘制出来的,如果有什么不同的看法,或者有什么不对的地方,请大家指出评论!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/132705
推荐阅读
相关标签
  

闽ICP备14008679号