d3.js-简单网络拓扑图实现

一.代码如下


<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
<body>
        <div id="tpContainer"></div>
        <script src ="http://d3js.org/d3.v3.min.js"></script>
        <script>
            var data = {
                "nodes": [
                    {
                        "name": "node-122",
                        "vmType": "server",
                        "image": "img/server_node.png"
                    }, {
                        "name": "dst1",
                        "vmType": "1",
                        "image": "img/vnf_node.png"
                    }, {
                        "name": "vnf1",
                        "vmType": "2",
                        "image": "img/vnf_node.png"
                    }, {
                        "name": "node-123",
                        "vmType": "server",
                        "image": "img/server_node.png"
                    }, {
                        "name": "vnf2",
                        "vmType": null,
                        "image": "img/vnf_node.png"
                    }, {
                        "name": "src1",
                        "vmType": "0",
                        "image": "img/vnf_node.png"
                    }
                ],
                "lines": [
                    {
                        "source": 0,
                        "target": 1,
                        "active": true
                    }, {
                        "source": 0,
                        "target": 2,
                        "active": true
                    }, {
                        "source": 0,
                        "target": 3,
                        "active": false
                    }, {
                        "source": 3,
                        "target": 4,
                        "active": false
                    }, {
                        "source": 3,
                        "target": 5,
                        "active": true
                    }
                ]
            };
        renderTp(data.nodes,data.lines);
        function renderTp(nodes,edges){
            var width  = 500;
            var height = 300;
            var img_w = 40;
            var img_h = 40;
            var text_dx = -20;
            var text_dy = 20;
            var drag = d3.behavior.drag()
                .origin(function(d) {
                    return d;
                })
                .on("dragstart", dragstarted)
                .on("drag", dragged)
                .on("dragend", dragended);
            var zoom=d3.behavior.zoom()
            .scaleExtent([-10,10]).on("zoom",zoomed);
            var svg = d3.select("#tpContainer").append("svg")
           .attr("width",width).attr("height",height)
           .style("pointer-events", "all").call(zoom);
            var g   = svg.append("g").attr("class","graphCon");
            var edges_line = g.selectAll("line")
                                .data(edges)
                                .enter()
                                .append("line")
                                .style("stroke",function(d,i){
                                    if(d.active==true){
                                        return "#f00";
                                    }
                                    return "#000";
                                })
                                .style("stroke-width",2);
            var nodes_img = g.selectAll("image").data(nodes)
            .enter().append("image")
                .attr("width",function(d){
                    return img_w;
                })
                .attr("height",function(d){
                    return img_h;
                })
                .attr("xlink:href",function(d){
                    if(d.vmType=="0"||d.vmType=="1"){
                        return "img/active_src_node.png";
                    }else if(d.vmType=="2"){
                        return "img/active_vnf_node.png";
                    }
                    return d.image;
                }).call(drag);

            var nodes_text = g.selectAll(".nodetext")
                                .data(nodes)
                                .enter()
                                .append("text")
                                .attr("class","nodetext")
                                .attr("dx",text_dx)
                                .attr("dy",text_dy)
                                .text(function(d){
                                    return d.name;
                                });
            //定义力学图布局
            var force    = d3.layout.force().nodes(nodes)
            .links(edges)
            .size([width,height])
            .linkDistance(function(d){
            if(d.source.vmType=="server"&&
                d.target.vmType=="server"){
                    return 200;
                }
                return 40;
            })
            .charge(-700).start().on("tick", function(){
               //限制结点的边界
                nodes.forEach(function(d,i){
                d.x = d.x - img_w/2 < 0? img_w/2 : d.x ;
                d.x = d.x + img_w/2 > width ? width - img_w/2 : 
                d.x ; 
                d.y = d.y - img_h/2 < 0? img_h/2 : d.y ;
                d.y = d.y + img_h/2 + text_dy > height ? 
                height - img_h/2 - text_dy : d.y ;
                });

        //更新连接线的位置
        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; });
        //更新结点图片和文字
        nodes_img.attr("x",function(d){
            return d.x - img_w/2; 
        });
        nodes_img.attr("y",function(d){ 
            return d.y - img_h/2; 
        });                  
        nodes_text.attr("x",function(d){ return d.x; });
        nodes_text.attr("y",function(d){ 
            return d.y + img_h/2; 
       });                   
       //画阴影
       var convex_hulls = function(nodes) {
            var  _h, i;
            var hulls = {};
            var k = 0;
            var offset = 65;
            while(k < nodes.length) {
                var n = nodes[k];
            if(n.vmType=="server"){
               _h = hulls['_'+n.index] || (hulls['_'+n.index] 
               = []);
               _h.push([n.x - offset, n.y - offset]);
               _h.push([n.x - offset, n.y + offset]);
               _h.push([n.x + offset, n.y - offset]);
               _h.push([n.x + offset, n.y + offset]);
            }                       
            ++k;
        }
        var hullset = [];
        for(i in hulls) {
        if({}.hasOwnProperty.call(hulls, i)) {
            hullset.push({
                group: i,
                path: d3.geom.hull(hulls[i])
            });
        }
    }
    return hullset;
};                              
    var curve = d3.svg.line().interpolate('cardinal-closed')
    .tension(0.85);
    var fill = d3.scale.category10();
    g.selectAll('path.hulls')
    .data(convex_hulls(g.selectAll("image")
    .data())).attr('d', function(d) {
        return curve(d.path);
    }).enter().insert('path', 'image')
    .style('fill', function(d) {
        return fill(d.group);
    }).style('stroke', function(d) {
        return fill(d.group);
    }).style('stroke-linejoin', 'round')
    .style('stroke-width', 10).style('opacity', 0.2);

});
function zoomed(){
g.attr(“transform”,
“translate(“+d3.event.translate+”)scale(” +
d3.event.scale + “)”);
}
function dragstarted(d) {
d3.event.sourceEvent.stopPropagation();
d3.select(this).classed(“dragging”, true);
force.start();
}

        function dragged(d) {
            d.x = d3.event.x;
            d.y = d3.event.y;
        }

        function dragended(d) {
            d3.select(this).classed("dragging", false);
        }
     }
    </script>
</body>
</html>
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wl_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值