【问题标题】:D3 treemap json implementation with d3.nest使用 d3.nest 实现 D3 树图 json
【发布时间】:2018-10-11 03:19:48
【问题描述】:

<!DOCTYPE html>
<meta charset="utf-8">
<head>
	<title>My treemap</title>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.min.js"></script>

</head>
<style>

body {
  font: 10px sans-serif;
  position: relative;
}

.node {
  box-sizing: border-box;
  line-height: 1em;
  overflow: hidden;
  position: absolute;
  white-space: pre;
  background: #ddd;
}

.node-label,
.node-value {
  margin: 4px;
}

.node-value {
  margin-top: -2px;
}

.node-value {
  font-weight: bold;
}
</style>
<body>
<svg width="1000" height="1000">
    <g></g>
  </svg>
  <script>
const margin = {top: 40, right: 10, bottom: 10, left: 10};
   var   width = 960 - margin.left - margin.right;
   var   height = 960 - margin.top - margin.bottom;
   var 	 color = d3.scaleOrdinal().range(d3.schemeCategory20b);
  	var treemap = d3.treemap()
	    .size([width, height])
	    .padding(1)
	    .round(true);
  	var json_data=d3.json("https://raw.githubusercontent.com/vega/vega/master/docs/data/cars.json", function(error, data) {
 	 if (error) throw error;
 	 	var nested_data = d3.nest()
 	 	.key(function(d) { return d.Origin; })
 	 	.key(function(d) { return d.Cylinders; })
 	 	.key(function(d) { return d.Miles_per_Gallon; })
 	 	.rollup(function(leaves){return {"value" : leaves.length}
 	 	})
 	 	.entries(data);
 	 	console.log(nested_data);
 	 	var root = d3.hierarchy(nested_data);
 	 	root.sum(function(d) {
 	 		return d.value;})

        treemap(root);
        var nodes = d3.select('svg g')
          .selectAll('g')
          .data(root.descendants())
          .enter()
          .append('g')
          .attr('transform', function(d) {return 'translate(' + [d.x0, d.y0] + ')'})

        nodes
          .append('rect')
          .attr('width', function(d) { return (d.x1 - d.x0)*10; })
          .attr('height', function(d) { return (d.y1 - d.y0)*10; })
          .attr('fill', function(d){ return color(d.data.key);
          })

        nodes
          .append('text')
          .text(function(d) {
            return d.data.key;})


		
 	 });
 	
  </script>
</body>

我正在尝试使用非分层数据结构(示例 cars.json 数据结构)创建树形图。现在我很困惑为什么我的代码在浏览器上没有显示任何内容。 我在将嵌套键和值附加到树的根和节点时遇到了麻烦。有人可以向我解释一下吗? 另外,你能告诉我我的代码有什么问题吗?

【问题讨论】:

  • 您使用的是哪个版本的 d3?对于我机器上的任何版本,我都无法让您的代码在前几行之外运行。
  • 我为我的案例添加了代码 sn-p 以便于编辑。你可以通过它查看。

标签: javascript json d3.js data-visualization


【解决方案1】:

您的代码几乎完成了;唯一缺少的是您需要在层次结构中添加一个假根节点,为子节点指定访问器,并修复叶节点的值,叶节点需要移除额外的嵌套层。

叶节点值:

var nested_data = d3.nest()
[...]
.rollup(function(leaves) {
  return {
    value: leaves.length
  }
})
.entries(data);

导致叶节点如下:

{ value: { value: 5 } }

rollup 调用中删除多余的value:

var nested_data = d3.nest()
[...]
.rollup(function(leaves) {
  return leaves.length
})
.entries(data);

现在你的叶子节点看起来像这样:

{ value: 5 }

假根节点

通过添加假根,确保所有嵌套数据都收集在同一层次结构中:

d3.hierarchy({ values: nested_data })

子节点访问器

指定子节点的访问器,否则 d3 将查找 x.children,如果不存在,则假定该节点是叶子节点:

d3.hierarchy({ value: nested_data }, function(d) { return d.values })

结果:

const margin = {
  top: 40,
  right: 10,
  bottom: 10,
  left: 10
};
var width = 960 - margin.left - margin.right;
var height = 960 - margin.top - margin.bottom;
var color = d3.scaleOrdinal().range(d3.schemeCategory20b);
var treemap = d3.treemap()
  .size([width, height])
  .padding(1)
  .round(true);
var json_data = d3.json("https://raw.githubusercontent.com/vega/vega/master/docs/data/cars.json", function(error, data) {
  if (error) throw error;
  var nested_data = d3.nest()
    .key(function(d) {
      return d.Origin;
    })
    .key(function(d) {
      return d.Cylinders;
    })
    .key(function(d) {
      return d.Miles_per_Gallon;
    })
    .rollup(function(leaves) {
      return leaves.length
    })
    .entries(data);

  var root = d3.hierarchy({
      values: nested_data
    }, d => d.values)
    .sum(function(d) {
      return d.value;
    })

  treemap(root);
  var nodes = d3.select('svg g')
    .selectAll('g')
    .data(root.descendants())
    .enter()
    .append('g')
    .attr('transform', function(d) {
      return 'translate(' + [d.x0, d.y0] + ')'
    })

  nodes
    .append('rect')
    .attr('width', function(d) {
      return (d.x1 - d.x0) * 10;
    })
    .attr('height', function(d) {
      return (d.y1 - d.y0) * 10;
    })
    .attr('fill', function(d) {
      return color(d.data.key);
    })

  nodes
    .append('text')
    .text(function(d) {
      return d.data.key;
    })
});
body {
  font: 10px sans-serif;
  position: relative;
}

.node {
  box-sizing: border-box;
  line-height: 1em;
  overflow: hidden;
  position: absolute;
  white-space: pre;
  background: #ddd;
}

.node-label,
.node-value {
  margin: 4px;
}

.node-value {
  margin-top: -2px;
}

.node-value {
  font-weight: bold;
}
<title>My treemap</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.min.js"></script>

<svg width="1000" height="1000">
    <g></g>
  </svg>

【讨论】:

  • 非常感谢。我很难理解 D3 中的这些关系。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-18
  • 2016-09-03
相关资源
最近更新 更多