D3 TreeMap调用导致x0、x1、y0、y1值为NaN

3
我正在构建一个D3 treemap 可视化,但遇到了一些问题。
我已经能够填充我的初始树状图,但我想通过点击交互引入修改。为了做到这一点,我需要在每次点击时重新计算新的布局(然后稍后对其进行一些处理),使用先前(当前显示)数据的子集来执行此操作。
我编写了一个sum函数,它按照我想要的方式工作,并填充了new_root对象中每个Nodevalue属性。据我所知,这是在new_root上运行d3.treemap的唯一先决条件。以下是代码片段:
let treemap = d3.treemap()
    .tile(d3.treemapResquarify)
    .size([800, 400])
    .round(true)
    .paddingInner(1);

// later...

function object_is_direct_child(root, obj) {
    return (root.children.filter(child => (child.id === obj.name)).length > 0);
}

// ...much later...

// Create and bind the click event.
let click = function(d) {
    if (d.data.children.length > 0) {
        // Use the hover ID to get the underlying name attr (e.g. "Noise-hover" -> "Noise")
        let name = this.getAttribute("id").slice(0,-6);

        // Select the new root node.
        let new_root = root.children.find(c => c.id === name);

        // Sum.
        new_root = new_root.sum(node => ((object_is_direct_child(new_root, node)) ? node.n : 0));

        // Here is the problem area. This doesn't work as expected.
        treemap(new_root);            
    }
}

hover_rects.on("click", click);

这段话的意思是:“这应该会在 new_node 和其所有子节点上填充计算出来的 x0、x1、y0 和 y1 值。然而,new_node 和其所有子节点都是 NaN。我已经上传了我的代码到 Gist 上,请点击此处查看。”
1个回答

0

我能够使用以下 MWE 脚本进行调试,在 Node 中运行:

'use strict';

// Load data.
const tree = require('../threshold-tree');
const d3 = require('d3');
const assert = require('assert');

// Load in the data file as it would be loaded in the browser.
const fs = require('fs');
const csvString = fs.readFileSync('data/complaint_types.csv').toString();
const raw_data = d3.csvParse(csvString);

let tr = new tree.ThresholdTree(raw_data);
let hr = tr.as_hierarchy();
let root = d3.stratify().id(d => d.name).parentId(d => d.parent)(hr);

function object_is_direct_child(root, obj) {
    return (root.children.filter(child => (child.id === obj.name)).length > 0);
}

// Now the sum function itself.
function nodal_summer(node) {
    return ((object_is_direct_child(root, node)) ? node.n : 0);
}

root = root.sum(nodal_summer);

// Create our treemap layout factory function.
let treemap = d3.treemap()
    .tile(d3.treemapResquarify)
    .size([800, 400])
    .round(true)
    .paddingInner(1);

// Apply our treemap function to our data.
debugger;
treemap(root);

// Again...this is where it fails!
let new_root = root.children[0];
new_root.parent = null;
new_root = new_root.sum(node => ((object_is_direct_child(new_root, node)) ? node.n : 0));

debugger;
new_root = treemap(new_root);
console.log(treemap(new_root));

罪魁祸首是d3中的positionNode回调函数:
  function positionNode(node) {
    var p = paddingStack[node.depth],
    ...

paddingStack以长度为1的列表进行初始化,但是node.depth1,所以p被初始化为NaN,并从那里传播出去。

两种有效的修复方法如下:

  1. 使用node.copy()
  2. new_root.eachBefore(function(node) { node.depth--; })

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接