【问题标题】:How to make force layout graph in D3.js responsive to screen/browser size如何使 D3.js 中的强制布局图响应屏幕/浏览器大小
【发布时间】:2012-08-10 03:59:18
【问题描述】:

我有一个使用强制布局的图表,但它有一个固定的宽度w 和高度h

var svg = d3.select("#viz").append("svg")
            .attr("id", "playgraph")
            .attr("width", w)
            .attr("height", h)

var force = d3.layout.force()
              .nodes(nodes)
              .links(links)
              .charge(-1600)
              .linkDistance(45)
              .size([w, h]); 

尽管屏幕或浏览器窗口大小发生变化,但这会导致 svg 图形不会按比例缩小或缩小。为了使其具有响应性(即自动调整自身大小),我尝试使用viewBoxpreserveAspectRatio 属性:

var svg = d3.select("#viz").append("svg")
            .attr("id", "playgraph")
            .attr("width", w)
            .attr("height", h)
            .attr("viewBox", "0, 0, 600, 400")
            .attr("preserveAspectRatio", "xMidYMid meet");

不幸的是,这不起作用,因为当我调整浏览器窗口大小时没有任何反应。不知道力图的.size([w, h])跟这个有没有关系。

请阐明如何将viewBoxpreserveAspectRatio 属性与强制布局图一起使用。

【问题讨论】:

  • 您可能还想将重绘功能附加到window.onresize
  • 这个问题已经相当老了,但对于那些觉得它有用的人,您可能还需要考虑将节点限制在有界框内。调整大小时,节点将保留在屏幕上。示例:bl.ocks.org/mbostock/1129492

标签: javascript svg d3.js force-layout


【解决方案1】:

此处显示的解决方案:http://bl.ocks.org/mbostock/3355967 对我来说效果很好!

window.addEventListener('resize', resize); 

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

确保在添加所有行、节点等后运行 resize()。

【讨论】:

    【解决方案2】:

    Duopixel 非常接近我所需要的,除了我不知道他为什么嵌套了两个 <g> 元素并将事件侦听器附加到最外面的 <g> (还需要一个不可见的矩形来让 g 反应到整个空间的事件)。

    将侦听器附加到<svg> 本身更容易,然后您只需要一个内部<g>

    这是我的全屏强制导向示例:

    var width = 1000,
        height = 1000;
    
    var color = d3.scale.category20();
    
    var svg = d3.select("body")
        .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 + ")");
    }
    
    function draw_graph(graph) {
      var force = d3.layout.force()
          .charge(-120)
          .linkDistance(30)
          .nodes(graph.nodes)
          .links(graph.links)
          .size([width, height])
          .start();
    
      var link = vis.selectAll(".link")
          .data(graph.links)
          .enter().append("line")
          .attr("class", "link")
          .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", 5)
          .style("fill", function(d) { return color(d.group); })
          .call(force.drag);
    
      node.append("title")
          .text(function(d) { return d.name; });
    
      force.on("tick", function() {
        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; })
            .attr("cy", function(d) { return d.y; });
      });
    };
    
    draw_graph(data);
    

    【讨论】:

      【解决方案3】:

      问题不在.size() 内,而是您在.attr("width", w) .attr("height", h) 中说明了SVG 尺寸。去掉这两个属性就行了……

      var svg = d3.select("#viz").append("svg")
                  .attr("id", "playgraph")
                   //better to keep the viewBox dimensions with variables
                  .attr("viewBox", "0 0 " + w + " " + h )
                  .attr("preserveAspectRatio", "xMidYMid meet");
      

      http://jsfiddle.net/aaSjd/

      【讨论】:

      • 谢谢!所以现在 svg 图像调整大小。但是,如果不设置attr("width", ...)attr("height", ...),图像的宽度/高度似乎是当前浏览器窗口的宽度/高度。有什么办法可以在其他地方设置svg 元素的这两个维度,而不影响viewBoxpreserveAspectRatio 属性?
      • <style type="text/css">svg {display: block; width: 80%; margin: 0 auto;}</style> 应该可以帮助您入门。
      • 只是一个警告; viewBox 属性区分大小写!注意它应该是camelCase。使用属性viewbox 将不起作用。还交叉链接其他类似的问题/答案:stackoverflow.com/questions/9400615/…stackoverflow.com/questions/44833788/…
      猜你喜欢
      • 1970-01-01
      • 2016-05-31
      • 2013-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-17
      • 2010-12-21
      相关资源
      最近更新 更多