D3制作力导向图

<html>
<head>
    <meta charset="utf-8">
    <title>Force</title>
    <style>
        .nodetext {
            font-size: 12px ;
            font-family:"Times New Roman",Georgia,Serif;

            fill:#000000;
        }
        .attrtext {
            font-size: 12px ;
            font-family:"Times New Roman",Georgia,Serif;

            fill:#000000;
            fill-opacity:0.0;
        }
        .linetext {
            font-size: 18px ;
            font-family:"Times New Roman",Georgia,Serif;

            fill:#1f77b4;
            fill-opacity:0.0;
        }
        .circleImg {
            stroke: #ff7f0e;
            stroke-width: 1.5px;
        }
        .link {
            fill: none;
            stroke: #666;
            stroke-width: 2.5px;
        }

        #licensing {
            fill: green;
        }

        .link.licensing {
            stroke: green;
        }

        .link.resolved {
            stroke-dasharray: 0,2 1;
        }

        circle {
            fill: #ccc;
            /* stroke: #333; */
            /* stroke- 1.5px; */
        }

        text {
            font: 28px Microsoft YaHei;
            pointer-events: none;
            text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff;
        }

        .linetext {
            font-size: 20px ;
        }

        .container {
            height: 525px;
            width: 575px;
            border:2px solid #000;
            overflow-y: scroll;
            overflow-x: hidden;
        }

        svg {
            display: block;
            width: 200%;
            height: 200%;
        }
    </style></head>
<body>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script>

    // var width = 900;
    // var height = 800;
    var width = 1360,
        height = 1000;
    img_w = 40;
    img_h = 40;
    radius = 50;    //圆形半径
    radius1=3;

    var svg = d3.select("body").append("svg")
        .attr("width",width)
        .attr("height",height);


    //var data = "{{ data }}"
    d3.json("relation.json",function(error,root){

        if( error ){
            return console.log(error);
        }
        console.log(root);


        // high level nodes and edges
        var nodes = {};
        var links = root.edges;

        links.forEach(function(link) {
            link.source = nodes[link.source] || (nodes[link.source] = {name: link.source, label: link.label});
            link.target = nodes[link.target] || (nodes[link.target] = {name: link.target, label: link.label});

        });

        // // secondary nodes and edges
        // var secondary_nodes = {};
        var secondary_links = root.secondary_edges;
        secondary_links.forEach(function(link, index) {
            link.source = nodes[link.source] || (nodes[link.source] = {name: link.source, label: link.label,size: link.size});
            link.target = (nodes[index+"_"+link.target] = {name: link.target, label: link.label,size: link.size});
            links.push(link);
            index++;
        });




        // debugger
        console.log(nodes);
        console.log(links);


        //         //D3力导向布局
        var force = d3.layout.force()
            .nodes(d3.values(nodes))
            .links(links)
            .size([width,height])
            .linkDistance(function(d) {
                if (d.label != "property") {
                    return 280;
                }
                return 150;
            })
            .charge(-1500)
            .on("tick",tick)
            .start();

        //
        var edges_line = svg.selectAll("line")
            .data(force.links())
            .enter()
            .append("line")
            .style("stroke","#9dc477")
            .style("stroke-width",1)
            .on("mouseover",function(edge){
                //单击时让连接线加粗
                edges_line.style("stroke-width",function(line){
                    if(line.source.name==edge.source.name && line.target.name==edge.target.name){
                        return 4;
                    }
                    else {
                        return 0.5;
                    }
                });
            })
            .on("mouseout",function(edge){
                edges_line.style("stroke-width",function(line){
                    return 0.5;
                });
            });


        //边上的文字(人物之间的关系)
        var edges_text = svg.append("g").selectAll(".linetext")
            .data(force.links())
            .enter()
            .append("text")
            .attr("class","linetext")
            .text(function(d){
                return d.relation;
            })
            .style("fill-opacity", 1.0)
            .call(force.drag);

        var circle = svg.append("g").selectAll("circle")
            .data(force.nodes())
            .enter().append("circle")
            //    .style("fill", "#99BBFF")
            .style("fill", function(node){
                var color;//圆圈背景色
                var link=links[node.index];
                if(node.label=="relation"){
                    color="#e9b99f";
                }
                else{
                    color="#afd1fc";
                }
                return color;
            })
            .attr("r", radius)
            .attr("r", function(d) {
                if (d.label == "property") {
                    return Math.sqrt(d.size*65);
                }
                return radius;


            })
            .on("click",function(node){
                //单击时让连接线加粗
                edges_line.style("stroke-width",function(line){
                    console.log(line);
                    if(line.source.name==node.name || line.target.name==node.name){
                        return 4;
                    }else{
                        return 0.5;
                    }
                });
            })
            .call(force.drag)
            .on("mouseover",function(d,i){
                //显示连接线上的文字
                edges_text.style("fill-opacity",function(edge){
                    if( edge.source === d || edge.target === d ){
                        return 1.0;
                    }
                });
            })
            .on("mouseout",function(d,i){
                //隐去连接线上的文字
                edges_text.style("fill-opacity",function(edge){
                    if( edge.source === d || edge.target === d ){
                        return 0.0;
                    }
                });
            });

        circle.append("svg:title")
            .text(function(node) {
                return "双击可查看详情"
            });

        var text_dx =0;
        var text_dy = -80;
        var text = svg.append("g").selectAll("text")
            .data(force.nodes())
            .enter()
            .append("text")
            .attr("dy", ".35em")
            .attr("text-anchor", "middle")//在圆圈中加上数据
            .style('fill', "#000000")
            .attr('x',function(d){
                if (d.label == "property") {
                    if (Math.sqrt(d.size*65)>15){
                        // console.log(d.name+"---"+ d.name.length);
                        var re_en = /[a-zA-Z]+/g;
                        //如果是全英文,不换行
                        if(d.name.match(re_en)){
                            d3.select(this).append('tspan')
                                .attr('x',0)
                                .attr('y',-2)
                                .text(function(){return d.name;});
                        }
                        //如果小于四个字符,不换行
                        else if(d.name.length<=6){
                            d3.select(this).append('tspan')
                                .attr('x',0)
                                .attr('y',-6)
                                .text(function(){return d.name;});
                        }else{
                            var top=d.name.substring(0,6);
                            var bot=d.name.substring(6,d.name.length);

                            d3.select(this).text(function(){return '';});

                            d3.select(this).append('tspan')
                                .attr('x',0)
                                .attr('y',-7)
                                .text(function(){return top;});

                            d3.select(this).append('tspan')
                                .attr('x',0)
                                .attr('y',10)
                                .text(function(){return bot;});
                        }
                    }
                    else{

                        // console.log(d.name+"---"+ d.name.length);
                        var re_en = /[a-zA-Z]+/g;
                        //如果是全英文,不换行
                        if(d.name.match(re_en)){
                            d3.select(this).append('tspan')
                                .attr('x',0)
                                .attr('y',-22)
                                .text(function(){return d.name;});
                        }
                        //如果小于四个字符,不换行
                        else if(d.name.length<=6){
                            d3.select(this).append('tspan')
                                .attr('x',0)
                                .attr('y',-16)
                                .text(function(){return d.name;});
                        }else{
                            var top=d.name.substring(0,6);
                            var bot=d.name.substring(6,d.name.length);

                            d3.select(this).text(function(){return '';});

                            d3.select(this).append('tspan')
                                .attr('x',0)
                                .attr('y',-7)
                                .text(function(){return top;});

                            d3.select(this).append('tspan')
                                .attr('x',0)
                                .attr('y',10)
                                .text(function(){return bot;});
                        }
                    }
                }
                else{
                    if (d.label == "relation") {
                        // console.log(d.name+"---"+ d.name.length);
                        var re_en = /[a-zA-Z]+/g;
                        //如果是全英文,不换行
                        if(d.name.match(re_en)){
                            d3.select(this).append('tspan')
                                .attr('x',0)
                                .attr('y',-2)
                                .text(function(){return d.name;});
                        }
                        //如果小于四个字符,不换行
                        else if(d.name.length<=6){
                            d3.select(this).append('tspan')
                                .attr('x',0)
                                .attr('y',-6)
                                .text(function(){return d.name;});
                        }else{
                            var top=d.name.substring(0,6);
                            var bot=d.name.substring(6,d.name.length);

                            d3.select(this).text(function(){return '';});

                            d3.select(this).append('tspan')
                                .attr('x',0)
                                .attr('y',-7)
                                .text(function(){return top;});

                            d3.select(this).append('tspan')
                                .attr('x',0)
                                .attr('y',10)
                                .text(function(){return bot;});
                        }
                    }



                }





            });
        //直接显示文字
        /*.text(function(d) {
        return d.name; */
        // });


        function tick() {
            //path.attr("d", linkArc);//连接线
            circle.attr("transform", transform1);//圆圈
            text.attr("transform", transform2);//顶点文字

            //更新连接线的位置
            edges_line.attr("x1",function(d){ return d.source.x; });
            edges_line.attr("y1",function(d){ return d.source.y; });
            edges_line.attr("x2",function(d){ return d.target.x; });
            edges_line.attr("y2",function(d){ return d.target.y; });


            //更新连接线上文字的位置
            edges_text.attr("x",function(d){ return (d.source.x + d.target.x) / 2 ; });
            edges_text.attr("y",function(d){ return (d.source.y + d.target.y) / 2 ; });
        }

        //设置圆圈和文字的坐标
        function transform1(d) {
            return "translate(" + d.x + "," + d.y + ")";
        }
        function transform2(d) {
            return "translate(" + (d.x) + "," + d.y + ")";
        }
    });

</script>
</body>
</html>

json文件格式

结果图为:

原文地址:https://www.cnblogs.com/qing0228/p/11196894.html