d3v4 Zoomable Treemap - 如何避免覆盖子rects?

时间:2018-02-03 02:57:55

标签: d3.js layout treemap

任何人都可以建议如何删除'重叠' Martin Meier' Zoomable Treemap v4(叠加)'中树形图布局的一个方面 https://bl.ocks.org/me1er/c64479f1ac8a5f993027f40a36c35dd9

我用Martin的代码创建的笔:https://codepen.io/meerkat00/pen/bLpbgZ

我认为Martin的树形图是基于Mike Bostock的(d3v3)Zoomable Treemap @ https://bost.ocks.org/mike/treemap

我想使用d3v4版本的各个方面作为我正在研究的d3v4树形图的基础。我将进行各种更改,包括处理多个度量,因此我可以扩展自定义accumulate(),例如。

但是,我很难修改如何修改Martin的树形图以完成子矩形的非重叠布局,例如Mike的原始可缩放树形图。

请注意,我的笔被修改为使用标准d3 flare api数据,以便直接比较这两个树形图实现之间的布局。

Mike B< d3v3代码的相关摘录:

var treemap = d3.layout.treemap()
.children(function(d, depth) { return depth ? null : d._children; })
.sort(function(a, b) { return a.value - b.value; })
.ratio(height / width * 0.5 * (1 + Math.sqrt(5)))
.round(false);

### snip ###

initialize(root);
accumulate(root);
layout(root);
display(root);

function initialize(root) {
   root.x = root.y = 0;
   root.dx = width;
   root.dy = height;
   root.depth = 0;
}

// Aggregate the values for internal nodes. This is normally done by the
// treemap layout, but not here because of our custom implementation.
// We also take a snapshot of the original children (_children) to avoid
// the children being overwritten when when layout is computed.
function accumulate(d) {
    return (d._children = d.children)
    ? d.value = d.children.reduce(function(p, v) { return p + accumulate(v); }, 0)
    : d.value;
}

// Compute the treemap layout recursively such that each group of siblings
// uses the same size (1×1) rather than the dimensions of the parent cell.
// This optimizes the layout for the current zoom state. Note that a wrapper
// object is created for the parent node for each group of siblings so that
// the parent’s dimensions are not discarded as we recurse. Since each group
// of sibling was laid out in 1×1, we must rescale to fit using absolute
// coordinates. This lets us use a viewport to zoom.
function layout(d) {
    if (d._children) {
        treemap.nodes({_children: d._children});
        d._children.forEach(function(c) {
            c.x = d.x + c.x * d.dx;
            c.y = d.y + c.y * d.dy;
            c.dx *= d.dx;
            c.dy *= d.dy;
            c.parent = d;
            layout(c);
      });
  }
}

来自Martin的d3v4代码的相关差异摘录:

treemap = d3.treemap()
    .size([width, height])
    .round(false)
    .paddingInner(1);
}

var root = d3.hierarchy(data)
    .eachBefore(function(d) { d.id = (d.parent ? d.parent.id + "." : "") + d.data.shortName; })
    .sum((d) => d.size)
    .sort(function(a, b) {
    return b.height - a.height || b.value - a.value; });

initialize(root);
accumulate(root);
layout(root);
treemap(root);
display(root);

function layout(d) {
    if (d._children) {
        d._children.forEach(function(c) {
        c.x0 = d.x0 + c.x0 * d.x1;
        c.y0 = d.y0 + c.y0 * d.y1;
        c.x1 *= d.x1;
        c.y1 *= d.y1;
        c.parent = d;
        layout(c);
});

非常感谢

1 个答案:

答案 0 :(得分:3)

我最终自己搞清楚了。定位错误的子项是由于v3布局坐标模型(x / dx,y / dy)到v4布局坐标模型(x0 / x1,y0 / y1)的端口不正确。

...实例

1)在函数rect()中,从原始v3样本计算宽度/高度:
    x(d.x + d.dx) - x(d.x)
    y(d.y + d.dy) - y(d.y)

像这样移植到v4:
    x(d.x0 + d.x1) - x(d.x0)
    y(d.y0 + d.y1) - y(d.y0)

我的v4修复:
    x(d.x1) - x(d.x0)
    y(d.y1) - y(d.y0)

2)在功能布局()中,原始v3样本的宽度值:
    dx

如此移植到v4:
    d.x1

我的v4修复:
    d.x1 - d.x0

工作代码在我的笔下。请参阅原始问题顶部附近的第二段,以获取笔链接。

Pic of fixed D3V4 Zoomable Treemap