我正在构建一个D3 treemap可视化,而且我遇到了麻烦。
我已经能够填充我的初始树形图,但我想通过点击互动对其进行修改。为了做到这一点,我需要每次点击重新计算一个新的布局(然后再用它做一些事情),使用我之前(当前显示的)数据的子集来做到这一点。
我已经编写了sum函数,可以按照我的意愿运行,并填充value
对象中每个Node
的{{1}}属性。据我所知,这是在new_root
上运行d3.treemap
的唯一先决条件。这是代码片段:
new_root
此应填充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);
及其所有子子的计算出的x0, x1, y0, y1
值。相反,new_node
及其所有孩子都是NaN。
我已经上传了我的要点,accessible here。
答案 0 :(得分: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));
罪魁祸首是positionNode
内的d3
回调:
function positionNode(node) {
var p = paddingStack[node.depth],
...
paddingStack
被初始化为长度为1的列表,但node.depth
为1
,因此p
被初始化为NaN
,从那里传播
两个有效的修复方法是:
node.copy()
。new_root.eachBefore(function(node) { node.depth--; })
。