首页 > 解决方案 > d3 circle pack - 访问数据(用于文本标签)

问题描述

我有一个修改过的圆形包实现,我在其中添加彼此相邻的根(而不是在一个巨大的圆圈中)。到目前为止,我一直没有想到的是在我创建了圆圈包之后,如果我想向每个圆圈添加文本,我该如何检索数据。这是我正在使用的内容:

var margins = {top:20, bottom:300, left:30, right:100};

var height = 600;
var width = 1080;

var totalWidth = width+margins.left+margins.right;
var totalHeight = height+margins.top+margins.bottom;

var svg = d3.select('body')
    .append('svg')
    .attr('width', totalWidth)
    .attr('height', totalHeight);

var graphGroup = svg.append('g')
    .attr('transform', "translate("+margins.left+","+margins.top+")");

//var tsvData = d3.tsv('circle-pack-data.tsv');

//tsvData.then(function(rawData) {

/*
  var data = rawData.map(function(d) {
    return {id:d.id, parentId:d.parentId, size:+d.size}
  });
*/


  var data = [
    [
    {'id':'1Q19'},
    {'id':'pooled','parentId':'1Q19','size':29.5},
    {'id':'spv','parentId':'1Q19', 'size':11},
    {'id':'single','parentId':'1Q19', 'size':200}
  ],

  [
  {'id':'2Q19'},
  {'id':'pooled','parentId':'2Q19','size':31},
  {'id':'spv','parentId':'2Q19', 'size':15},
  {'id':'single','parentId':'2Q19', 'size':171}
],

[
{'id':'3Q19'},
{'id':'pooled','parentId':'3Q19','size':28},
{'id':'spv','parentId':'3Q19', 'size':12},
{'id':'single','parentId':'3Q19', 'size':152}
],

[
{'id':'4Q19'},
{'id':'pooled','parentId':'4Q19','size':25},
{'id':'spv','parentId':'4Q19', 'size':214},
{'id':'single','parentId':'4Q19', 'size':101}
],
];

var colorMap = {
  '1Q19':"#e7eef8",
  '2Q19':"#e7eef8",
  '3Q19':"#e7eef8",
  '4Q19':"#e7eef8",
  'pooled':"#f6d18b",
  'spv':"#366092",
  'single':"#95b3d7"
};

    for (var j=0; j <(data.length); j++) {

  var vData = d3.stratify()(data[j]);

  var vLayout = d3.pack().size([250, 250]);

  var vRoot = d3.hierarchy(vData).sum(function (d) { return d.data.size; });
  var vNodes = vRoot.descendants();
  vLayout(vRoot);

  var thisClass = "circ"+String(j);

  var vSlices = graphGroup.selectAll('.'+thisClass).data(vNodes).attr('class',thisClass).enter().append('g');

  //console.log(vNodes)

  vSlices.append('circle')
      .attr('cx', function(d, i) {
          return d.x+(j*300)
      })
      .attr('cy', function (d) { return d.y; })
      .attr('r', function (d) { return d.r; })
      .style('fill', function(d) { return colorMap[d.data.id]});

  vSlices.append('text')
      .attr('x', function(d,i) {return d.x+(j*300)})
      .attr('y', function(d) {return d.y})
      .attr('text-anchor','middle')
      .text(function(d) {return d.data.children.data.size});

}

//})
<script src="https://d3js.org/d3.v5.min.js"></script>

控制台日志显示我尝试访问的对象属性不存在,但具有讽刺意味的是,正是控制台对数据结构的映射导致我d.data.children.data.size首先进行选择。

我假设我这边有一些用户错误,但我真的没有成功解决问题。我已经尝试过d.data.children[0].data.size和其他类似的变化,但错误仍然存​​在。

问题

是否有更简单的万无一失(防垃圾)方法来访问size似乎深埋的财产vNodes?我能想到的最好的办法是制作一个可能像这样工作的独立对象:sizeMap[d.data.id],但这需要做很多工作,并且违背了使用 d3 的目的,我觉得。

标签: javascriptd3.js

解决方案


并非所有节点都包含对象size中的属性data。因此,您可以执行以下操作:

return d.data.data.size ? d.data.data.size : null

这是演示:

var margins = {
  top: 20,
  bottom: 300,
  left: 30,
  right: 100
};

var height = 600;
var width = 1080;

var totalWidth = width + margins.left + margins.right;
var totalHeight = height + margins.top + margins.bottom;

var svg = d3.select('body')
  .append('svg')
  .attr('width', totalWidth)
  .attr('height', totalHeight);

var graphGroup = svg.append('g')
  .attr('transform', "translate(" + margins.left + "," + margins.top + ")");

//var tsvData = d3.tsv('circle-pack-data.tsv');

//tsvData.then(function(rawData) {

/*
  var data = rawData.map(function(d) {
    return {id:d.id, parentId:d.parentId, size:+d.size}
  });
*/


var data = [
  [{
      'id': '1Q19'
    },
    {
      'id': 'pooled',
      'parentId': '1Q19',
      'size': 29.5
    },
    {
      'id': 'spv',
      'parentId': '1Q19',
      'size': 11
    },
    {
      'id': 'single',
      'parentId': '1Q19',
      'size': 200
    }
  ],

  [{
      'id': '2Q19'
    },
    {
      'id': 'pooled',
      'parentId': '2Q19',
      'size': 31
    },
    {
      'id': 'spv',
      'parentId': '2Q19',
      'size': 15
    },
    {
      'id': 'single',
      'parentId': '2Q19',
      'size': 171
    }
  ],

  [{
      'id': '3Q19'
    },
    {
      'id': 'pooled',
      'parentId': '3Q19',
      'size': 28
    },
    {
      'id': 'spv',
      'parentId': '3Q19',
      'size': 12
    },
    {
      'id': 'single',
      'parentId': '3Q19',
      'size': 152
    }
  ],

  [{
      'id': '4Q19'
    },
    {
      'id': 'pooled',
      'parentId': '4Q19',
      'size': 25
    },
    {
      'id': 'spv',
      'parentId': '4Q19',
      'size': 214
    },
    {
      'id': 'single',
      'parentId': '4Q19',
      'size': 101
    }
  ],
];

var colorMap = {
  '1Q19': "#e7eef8",
  '2Q19': "#e7eef8",
  '3Q19': "#e7eef8",
  '4Q19': "#e7eef8",
  'pooled': "#f6d18b",
  'spv': "#366092",
  'single': "#95b3d7"
};

for (var j = 0; j < (data.length); j++) {

  var vData = d3.stratify()(data[j]);

  var vLayout = d3.pack().size([250, 250]);

  var vRoot = d3.hierarchy(vData).sum(function(d) {
    return d.data.size;
  });
  var vNodes = vRoot.descendants();
  vLayout(vRoot);

  var thisClass = "circ" + String(j);

  var vSlices = graphGroup.selectAll('.' + thisClass).data(vNodes).attr('class', thisClass).enter().append('g');

  //console.log(vNodes)

  vSlices.append('circle')
    .attr('cx', function(d, i) {
      return d.x + (j * 300)
    })
    .attr('cy', function(d) {
      return d.y;
    })
    .attr('r', function(d) {
      return d.r;
    })
    .style('fill', function(d) {
      return colorMap[d.data.id]
    });

  vSlices.append('text')
    .attr('x', function(d, i) {
      return d.x + (j * 300)
    })
    .attr('y', function(d) {
      return d.y
    })
    .attr('text-anchor', 'middle')
    .text(function(d) {
      return d.data.data.size ? d.data.data.size : null
    });

}

//})
<script src="https://d3js.org/d3.v5.min.js"></script>


推荐阅读