在D3.js中有.append()的替代品吗?

时间:2014-03-19 19:10:01

标签: javascript css d3.js

.append()方法是将D3对象添加到HTML的唯一方法吗?

我使用append()方法将树形图添加到我的HTML文件的主体,但我想在一个元素中添加树形图。问题是append在当前元素之后添加,而不是在当前元素内。我想调整树形图的大小,以扩展到浏览器初始高度和宽度的100%like this。添加CSS似乎是最直接的方式。

我试图通过将树形图附加到div中的div来“欺骗”D3.js,但这不起作用。

也许我问的是错误的问题,我应该在d3.js脚本中调整树形图的大小?我试图更改bl.ock.org提供的默认样式,但我没有让树形图扩展到全屏。

以下是我认为初始化树形图的代码。

var margin = {top: 40, right: 10, bottom: 10, left: 10},
    width = 1000 - margin.left - margin.right,
    height = 650 - margin.top - margin.bottom;

var color = d3.scale.category20c();

var treemap = d3.layout.treemap()
    .size([width, height])
    .sticky(false)
    .value(function(d) { return d.size; });

var div = d3.select("body").append("div")
    .style("position", "relative")
    .style("width", (width + margin.left + margin.right) + "px")
    .style("height", (height + margin.top + margin.bottom) + "px")
    .style("left", margin.left + "px")
    .style("top", margin.top + "px");

以下是更改节点大小以容纳javascript值的代码。

var root;

socket.on('update', function(stream) {
  console.log('tweets')

  div.datum(root).selectAll(".node").remove();

  root = stream.masterlist;

  var node = div.datum(root).selectAll(".node")
      .data(treemap.nodes)
    .enter().append("div")
      .attr("class", "node")
      .call(position)
      .style("background", function(d) { return d.children ? color(d.name) : null; })
      .text(function(d) { return d.children ? null : d.name; });

  });


});

function position() {
  this.style("left", function(d) { return d.x + "px"; })
      .style("top", function(d) { return d.y + "px"; })
      .style("width", function(d) { return Math.max(0, d.dx - 1) + "px"; })
      .style("height", function(d) { return Math.max(0, d.dy - 1) + "px"; });
}

2 个答案:

答案 0 :(得分:4)

我会稍微改变一下这个问题。

我会使用viewBox attribute来保持可视化的坐标系不变。我个人喜欢<svg viewBox="-100 -100 200 200">,这意味着(-100, -100)是左上角,(100, 100)是右下角。您也可以选择0 0 100 100

然后我不会明确地在width元素上设置任何heightsvg,而是依靠CSS为它们提供正确的尺寸(比如display: block; width: 80%; margin: auto; height: 80%)和然后控制可视化如何使用preserveAspectRatio attribute进行缩放。通常,我发现默认值(xMidYMidmeet)对我来说已经足够了。但是,您的里程可能会有所不同。

这是使用此方法在容器大小更改时调整可视化大小而不重绘可视化的示例:http://jsfiddle.net/ss47m/

此处:容器的http://jsfiddle.net/ss47m/1/大小覆盖整个窗口。


另一种方法是绑定resize上的window事件(如nvd3 does with windowResize),并在每次窗口更改大小时重绘图表。我发现有点过分。

答案 1 :(得分:3)

首先,澄清:

  

问题是append在当前元素之后添加,而不是在当前元素内。

这不正确。如果您执行d3.select("div.parent").append("div"),则新div将在

内父div中,但在父内容中已有任何子内容之后。要使新元素成为父元素的第一个子元素,您可以d3.select("div").insert("div", function(){return this.children[0];})。但我不认为这真的是你的问题......

关于如何计算树形图以使其自动填充浏览器窗口的问题:

如果您只是希望地图填充窗口的初始大小,而不用担心调整大小,则需要(a)找出窗口大小; (b)将容器div的高度和宽度设置为该尺寸; (c)使用这些维度作为树形图函数的输入大小。

基本上,只需更改这些行:

width = 1000 - margin.left - margin.right,
height = 650 - margin.top - margin.bottom;

width = window.innerWidth - margin.left - margin.right,
height = window.innerHeight - margin.top - margin.bottom;

然后你的其余代码是相同的。

如果您还希望树形图按窗口缩放,则应使用百分比值设置子元素的位置和大小。如果使用[100,100]作为大小初始化树形图,那么这将是最简单的,然后您只需用"px"替换位置函数中的所有"%"

但是,您仍然需要一些CSS来使您的容器div填满浏览器窗口的完整大小并使用它调整大小。这有多棘手取决于你在页面布局中发生了多少其他事情。您可能还想查看this answer。如果您无法使CSS工作,您可以随时监听窗口大小调整事件,并根据窗口大小重置容器的宽度和高度。如果孩子的大小基于百分比,那么他们将调整为您为父母设置的任何大小。

最后,您可能希望在容器上设置min-heightmin-width属性,以确保您的树形图元素始终是一个合适的大小,即使它意味着滚动。