响应力指向具有不同节点半径的边界框的D3图

时间:2015-05-11 14:25:12

标签: javascript d3.js force-layout

我有一个响应力导向图,它工作得很好,除了我无法让它留在浏览器屏幕内。

建议创建边界框的D3代码是:

  node.attr("cx", function(d) { return d.x = Math.max(r, Math.min(width - r, d.x)); }) .attr("cy", function(d) { return d.y = Math.max(r, Math.min(height - r, d.y)); });

然而,这不起作用,因为我没有定义宽度(它是响应的)而我没有定义 r 因为它是一个函数,所以节点的大小不同。

我试着设置:

var r= function(d) {return d.instances;};

因为那是我放置节点大小的地方,但它不起作用...我看到的所有强制定向示例都使用相同大小的节点..我只是不熟悉javascript来形象解决方法......帮忙?

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<!DOCTYPE html>
<meta charset="utf-8">
<style type="text/css">
    
*{
    margin:0;
    padding:0;
}
/*
svg {
    display: block; 
    width: 100%; 
    margin: 0;
}
*/

.node {
  stroke: #fff;
  stroke-width: 1.5px;
}
    
    #graph{
     max-width:100%;
     height:100vh ;
    }

.link {
  stroke: #999;
  stroke-opacity: .6;
}
    
    .node-active{
  stroke: #555;
  stroke-width: 1.5px;
}
    
        .node:hover{
  stroke: #555;
  stroke-width: 1.5px;
}
    marker {
display:none;
    }
    
    .d3-tip {
  line-height: 1;
  font-weight: bold;
  padding: 12px;
  background: rgba(0, 0, 0, 0.8);
  color: #fff;
  border-radius: 2px;
}

.d3-tip.n:after {
  margin: -1px 0 0 0;
  top: 200%;
  left: 0;
}
    script {
        display:none;
    }

</style>
<body>
     <div id="graph"></div>
<script src="d3/d3.js"></script>
<script src="d3/d3tip.js"></script>
    <script type='text/javascript' src='http://code.jquery.com/jquery-1.11.0.js'></script>
<script>

var color = d3.scale.category20();

var force = d3.layout.force()
    .charge(-2010)
    .linkDistance(function(d) { return  d.distance; })
//    .size([width, height])
    .gravity(0.7);
    
//var width = 1000,
//    height = 1000;    
        
var svg = d3.select("#graph")
    .append("svg")
    .attr({
        "width": "100%",
        "height": "100%"
      })
//    .attr("viewBox", "0 0 " + width + " " + height )
    .attr("preserveAspectRatio", "xMidYMid meet")                   //.attr("pointer-events", "all")
    .call(d3.behavior.zoom().on("zoom", redraw));
    
var vis = svg
    .append('svg:g');

function redraw() {
  vis.attr("transform",
      "translate(" + d3.event.translate + ")"
      + " scale(" + d3.event.scale + ")");
}
    
var tip = d3.tip()
    .attr('class', 'd3-tip')
    .offset([-5, 0])
    .html(function (d) {
    return  d.name + "  (" + d.instances + ")";
})
    svg.call(tip);
    
    

d3.json("datawords.json", function(error, graph) {

  var link = vis.selectAll(".link")
      .data(graph.links)
    .enter().append("line")
      .attr("class", "link")
      .attr("width", function(d) { return d.totalLength; })
      .style("stroke-width", function(d) { return Math.sqrt(d.value); });

  var node = vis.selectAll(".node")
      .data(graph.nodes)
      .enter().append("circle")
      .attr("class", "node")
      .attr("r", function(d) {return d.instances;})
      .style("fill", function(d) { return color(d.instances); })
      .call(force.drag)
    .on('mouseover', tip.show)
    .on('mouseout', tip.hide)
    .on('click', connectedNodes)
  
 force
      .nodes(graph.nodes)
      .links(graph.links)
      .start();

  force.on("tick", function() {
    
    node[0].x = svg / 2;
    node[0].y = svg / 2;
      
      
    link.attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });
      
//      
//      node.attr("cx", function(d) { return d.x = Math.max(r, Math.min(width - r, d.x)); }) .attr("cy", function(d) { return d.y = Math.max(r, Math.min(height - r, d.y)); });
      
      
    node.attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
      
    node.each(collide(0.5));
    });
    
    
        
        ///////////////////

    
    //Toggle stores whether the highlighting is on
var toggle = 0;
//Create an array logging what is connected to what
var linkedByIndex = {};
for (i = 0; i < graph.nodes.length; i++) {
    linkedByIndex[i + "," + i] = 1;
};
graph.links.forEach(function (d) {
    linkedByIndex[d.source.index + "," + d.target.index] = 1;
});
//This function looks up whether a pair are neighbours
function neighboring(a, b) {
    return linkedByIndex[a.index + "," + b.index];
}
function connectedNodes() {
    if (toggle == 0) {
        //Reduce the opacity of all but the neighbouring nodes
        d = d3.select(this).node().__data__;
        node.style("opacity", function (o) {
            return neighboring(d, o) | neighboring(o, d) ? 1 : 0.1;
        });
        link.style("opacity", function (o) {
            return d.index==o.source.index | d.index==o.target.index ? 1 : 0.1;
        });
        //Reduce the op
        toggle = 1;
    } else {
        //Put them back to opacity=1
        node.style("opacity", 1);
        link.style("opacity", 1);
        toggle = 0;
    };
};
    
    var padding = 10, // separation between circles
    radius=15;

    function collide(alpha) {
  var quadtree = d3.geom.quadtree(graph.nodes);
  return function(d) {
    var rb = 4*radius + padding,
        nx1 = d.x - rb,
        nx2 = d.x + rb,
        ny1 = d.y - rb,
        ny2 = d.y + rb;
    
    quadtree.visit(function(quad, x1, y1, x2, y2) {
      if (quad.point && (quad.point !== d)) {
        var x = d.x - quad.point.x,
            y = d.y - quad.point.y,
            l = Math.sqrt(x * x + y * y);
          if (l < rb) {
          l = (l - rb) / l * alpha;
          d.x -= x *= l;
          d.y -= y *= l;
          quad.point.x += x;
          quad.point.y += y;
        }
      }
      return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
    });
  };
};
    window.addEventListener('resize', resize); 

function resize() {
    width = window.innerWidth, height = window.innerHeight;
    svg.attr("width", width).attr("height", height);
    force.size([width, height]).resume();
}
});

    

</script>
</body>

1 个答案:

答案 0 :(得分:0)

node.attr("cx", (function(w) {
        return function(d) { 
            var r = d.instances;
            return d.x = Math.max(r, Math.min(w - r, d.x));
        }
    })(width())) 

    .attr("cy", (function(h) {
        return function(d) {
            var r = d.instances;
            return d.y = Math.max(r, Math.min(h - r, d.y));
        }
    })(height()));  

width()height()定义为返回实时值的函数。