如何在D3中的堆栈布局中获取元素的键?

时间:2019-04-18 11:17:57

标签: d3.js

我想添加一个工具包来显示灾难的类型,这是堆栈数据的关键,我如何获得它?

.csv文件的格式如下:(原谅我不能拍照)

AllNaturalDisasters,Drought,Earthquake,ExtremeTemperature,ExtremeWeather,Flood,Impact,Landslide,MassMovementDry,VolcanicActivity,Wildfire,Year
5,2,null,null,1,1,null,null,null,1,null,1900
2,null,2,null,null,null,null,null,null,null,null,1901

在这里我创建一个堆栈

var stack = d3.stack()
  .keys(["Drought", "Earthquake", "ExtremeTemperature", "ExtremeWeather", "Flood", "Impact", "Landslide", "MassMovementDry", "VolcanicActivity", "Wildfire"]);

,然后将我的数据传递给它:var series = stack(dataset);datasetcsv文件中的所有数据。然后,我使用堆栈布局创建一个图表,如下所示:

var groups = svg.selectAll("g")
    .data(series)
    .enter()
    .append("g")
    .style("fill", function(d, i) {
        return colors(i);
    });

var rects = groups.selectAll("rect")
    .data(function(d) { return d; })
    .enter()
    .append("rect")
    .attr("x", function(d, i) {
        return xScale(i);
    })
    .attr("y", function(d) {
        return yScale(d[1]);
    })
    .attr("height", function(d) {
        return yScale(d[0]) - yScale(d[1]);
    })
    .attr("width", xScale.bandwidth())
    .append("title")
    .text(function (d) {
        return d.data.Year;
    });

问题就在这里

.append("title")
    .text(function (d) {
        return d.data.Year;
    });

我想添加一个工具包来显示灾难的类型,这是series中此数据的关键,如何获取它而不是年份?!

2 个答案:

答案 0 :(得分:1)

每个矩形都包含有关列(灾难年份)的信息,但是每个g都具有有关“行”(灾难类型)的信息。

堆栈会生成一个嵌套数组,其父级(我们用来创建g元素)包含灾难的键或类型

子级别代表包含年份的列。

孙子级别仅包含单个矩形。

因此,我们可以通过选择父项g来获取密钥:

.append("title")
  .text(function() {
     var rect = this.parentNode; // the rectangle, parent of the title
     var g = rect.parentNode;    // the g, parent of the rect.
     return d3.select(g).datum().key; // now we get the key.
  })

当然可以简化一点,但是我为了更好地评论而将其打破。

这允许更灵活的排序-而不是依赖固定索引。

这里使用的是您的数据:

var csv = d3.csvParse(d3.select("pre").text());


var stack = d3.stack().keys(["Drought", "Earthquake", "ExtremeTemperature", "ExtremeWeather", "Flood", "Impact", "Landslide", "MassMovementDry", "VolcanicActivity", "Wildfire"]);

var series = stack(csv);

var colors = d3.scaleOrdinal()
  .range(d3.schemeCategory10);
  
var xScale = d3.scaleBand()
  .domain([0,1])
  .range([0,300])
  
var yScale = d3.scaleLinear()
  .domain([0,6])
  .range([200,0]);

var svg = d3.select("svg");
  
var groups = svg.selectAll("g")
  .data(series)
  .enter()
  .append("g")
  .style("fill", function(d, i) {
     return colors(i);
   });

var rects = groups.selectAll("rect")
  .data(function(d) { return d; })
  .enter()
  .append("rect")
  .attr("x", function(d, i) {
    return xScale(i);
  })
  .attr("y", function(d) {
    return yScale(d[1]);
  })
  .attr("height", function(d) {
     return yScale(d[0]) - yScale(d[1]);
  })
  .attr("width", xScale.bandwidth())
  .append("title")
  .text(function (d) {
      var rect = this.parentNode;
      var g = rect.parentNode;
      return d3.select(g).datum().key;
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

<svg width="400" height="300"></svg>


<pre>AllNaturalDisasters,Drought,Earthquake,ExtremeTemperature,ExtremeWeather,Flood,Impact,Landslide,MassMovementDry,VolcanicActivity,Wildfire,Year
5,2,0,0,1,1,0,0,0,1,0,1900
2,0,2,0,0,0,0,0,0,0,0,1901</pre>

答案 1 :(得分:0)

好吧,我已经通过非常“低”的方法解决了这个问题。我创建了一个简单的函数:

function getKeys(d) {
            return series[parseInt(groups.selectAll("rect").data().indexOf(d) / series[0].length)].key;
        }

好吧,它是如此简单和粗糙,我仍然想知道一种更有效的方法!