2015-05-11 35 views
0

我有一个响应性的定向力图,它工作的很好,除了我不能让它留在浏览器屏幕内。响应力定向D3图与不同节点半径的包围盒

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>

回答

0

我不能发表评论,由于等级限制但是,我相信这个问题是从你的width/height variables引起的。取消您的var width/height的注释并将其更改为var width = innerWidth, height = innerHeight;。然后在你的svg中设置attr.attr('width', width).attr('height', height);

+0

这并没有打破它至少:)但我不知道它改变了什么...当我使用: var width = innerWidth, height = innerHeight; VAR SVG = d3.select( “#图形”) .append( “SVG”) .attr( '宽度',宽度) .attr( '高度',高度).... 然后取消注释: node.attr(“cx”,function(d){return dx = Math.max(r,Math.min(width - r,dx));}).attr(“cy”,function(d ){return dy = Math.max(r,Math.min(height -r,dy));}); 它说R是未定义的,所以边界框仍然没有工作。在加载和我想要加载的位置的屏幕截图: http://imgur.com/a/XDmIb – Jess

+0

我用你的建议,并定义了R as 'var r = function(d){return d.instances;};' 现在我得到意外的价值NaN解析y2 attirbute控制台错误(d3.js 672) – Jess

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()定义为返回实时值的函数。