D3.js如何在组条形图中唯一标识单个条形图

时间:2016-02-14 20:09:11

标签: javascript d3.js

我使用D3.js创建了组条形图。每组有2个酒吧。单击任何栏时,必须使用自定义警告框显示一些数据。现在,栏可以单击并显示数据。

var state = svg.selectAll(".TestSuite")
         .data(data)
         .enter().append("g")
         .attr("class", "TestSuite")
         .on("click", function(d,i) {
                if(i==0){
                Alert.render(d3.select(this).data()[0].FalseStatements);
                }else{
                 Alert.render(d3.select(this).data()[0].TrueStatements);
                }
            })
         .attr("transform", function (d) {
         return "translate(" + x0(d.TestSuite) + ",0)";
     });

但数据根据点击的栏数而有所不同。那么如何唯一地识别单个组中的每个单个栏。

这里“如果条件”我使用的不做我想要的东西。我该怎么纠正呢?

谢谢。

(假设一组条形图包含两个条形图,一个显示真实计数,另一组显示特定方案的错误计数。当我们单击显示真实计数的条形图时,它应显示已存在于数据中的“TrueStatements”。使用d3.select(this).data()[0].TrueStatements可以做到这一点。当有人点击显示错误计数的栏时,它应该出现在数据中已有的“FalseStatements”。使用d3.select(this).data()[0].FalseStatements可以做到这一点。我的问题是如何做我们确定显示真实计数的栏和显示错误计数的栏,以执行此任务。)

编辑:

如何获取条形图的数据(这是在for循环中)

originalDataSetForBarChart.push({
          TestSuite: "TS"+treeIndex,
          Pass: trueAppear,
          Fail: falseAppear,
          FalseStatements : falseStatement,
          TrueStatements : trueStatement
     });

条形图代码

 var margin = {
     top: 20,
     right: 10,
     bottom: 30,
     left: 40
 },
      
 width = 890 - margin.left - margin.right,
      
 height = 300 - margin.top - margin.bottom;

 var x0 = d3.scale.ordinal()
     .rangeRoundBands([0, width], .5);

 var x1 = d3.scale.ordinal();

 var y = d3.scale.linear()
     .range([height, 0]);

 var color = d3.scale.ordinal()
     .range(["#4169E1", "#800080"]);

 var xAxis = d3.svg.axis()
     .scale(x0)
     .orient("bottom");

 var yAxis = d3.svg.axis()
     .scale(y)
     .orient("left")
     .tickFormat(d3.format(""));
    
    
 var w = width + margin.left + margin.right;
    
 var h = height + margin.top + margin.bottom;
  
 var svg = d3.select(".chart1").append("svg")
           .attr("width", w)
           .attr("height", h)
           .append("g")
           .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

//svg.call(tip);

var xg = svg.append("g")
     .attr("class", "x axis")
     .attr("transform", "translate(0," + height + ")");

 var yg = svg.append("g")
     .attr("class", "y axis");

 yg.append("text")
     .attr("transform", "rotate(-90)")
     .attr("y", 6)
     .attr("dy", ".71em")
     .style("text-anchor", "end")
     .text("Count");

我使用以下方法在setInterval函数中将条形附加到此图表。

function update() {
     startTime_barChart = new Date().getTime();
     for (var i = 0; i < data.length; i++) {
         var testSuite = d3.keys(data[i]).filter(function (key) {
             return key !== "TestSuite";
         });

     }

     data.forEach(function (d) {
         d.trueFalseCount = testSuite.map(function (name) {
             return {
                 name: name,
                 value: +d[name]
             };
         });

     });

     x0.domain(data.map(function (d) {
         return d.TestSuite;
     }));
     x1.domain(testSuite).rangeRoundBands([0, x0.rangeBand()]);
     y.domain([0, d3.max(data, function (d) {
         return d3.max(d.trueFalseCount, function (d) {
             return d.value;
         });
     })]);
      
     //making the x axis/y axis
     xg.call(xAxis);
     yg.call(yAxis);
      
     //removing all the rectangles
     svg.selectAll(".TestSuite").remove();
    var tip_word; 
    var tip = d3.tip()
        .attr('class', 'd3-tip')
        .offset([-10, 0])
        .html(function(d) {
            tip_word= "<strong style='color:white'>"+
                            "Pass count :"+
                      "</strong>"+
                     " <span style='color:white'>" + d.True + 
                      "</span></br>"+
                     "<strong style='color:white'>"+
                            "Fail count :"+
                      "</strong>"+
                     " <span style='color:white'>" + d.False + 
                      "</span>";
            return word;
        });
    
     var state = svg.selectAll(".TestSuite")
         .data(data)
         .enter().append("g")
         .attr("class", "TestSuite")
         .on("click", function(d,i) {
                if(i%2 == 0){//How to set this condition
                  
                Alert.render(d3.select(this).data()[0].FalseStatements);
                }else{
                    
                 Alert.render(d3.select(this).data()[0].TrueStatements);
                }
               
            })
         .attr("transform", function (d) {
         return "translate(" + x0(d.TestSuite) + ",0)";
     });
    
    svg.call(tip);
     
     state.selectAll("rect")
         .data(function (d) {
         return d.trueFalseCount;})
         .enter().append("rect")
         .attr("width", x1.rangeBand())
         .attr("x", function (d) {
         return x1(d.name);
     })
         .attr("y", function (d) {
         return y(d.value);
     })
         .attr("height", function (d) {
         return height - y(d.value);
     })
         .style("fill", function (d) {
         return color(d.name);
     });
 
      
  if(barChartLegentController==1){    
   var legend = svg.selectAll(".legend")
      .data(testSuite.slice().reverse())
    .enter().append("g")
      .attr("class", "legend")
      .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });

   legend.append("rect")
      .attr("x", width - 18)
      .attr("width", 18)
      .attr("height", 18)
      .style("fill", color);

   legend.append("text")
      .attr("x", width - 24)
      .attr("y", 9)
      .attr("dy", ".35em")
      .style("text-anchor", "end")
      .text(function(d) { return d; });
      
  barChartLegentController=2;      
  }
    
  endTime_barChart = new Date().getTime();
  var totalbar = (endTime_barChart-startTime_barChart)/1000;     
  //alert('Total bar time : '+ totalbar+' seconds');
 }

1 个答案:

答案 0 :(得分:0)

我不确定我是否完全理解你的要求,但识别任何元素/实体的最佳方法是使用id,如下所示:

d3.select(this).attr(id, function(d, i) {return 'bar_' + i});

在创建条形图的迭代函数中添加它。通过这种方式,您可以使用d3.select('#bar_1)从代码中的任意位置选择它们。

如果您只想识别每个栏,它将是这样的:

var state = svg.selectAll(".TestSuite")
  .data(data)
  .enter().append("g")
  .attr("id", function(d,i) {return 'bar_' + i})
  .attr("class", "TestSuite")
  .on("click", function(d,i) {
    if(i==0){
      Alert.render(d3.select(this).data()[0].FalseStatements);
    }else{
      Alert.render(d3.select(this).data()[0].TrueStatements);
    }
  })
  .attr("transform", function (d) {
    return "translate(" + x0(d.TestSuite) + ",0)";
});

如果您希望识别每个栏的ID与其内容相关(真或假陈述),我建议如下:

var state = svg.selectAll(".TestSuite")
  .data(data)
  .enter().append("g")
  .attr("class", "TestSuite")
  .on("click", function(d,i) {
    var barId;
    if(i==0){
      barId = 'falseBar_' + i;
      Alert.render(d3.select(this).data()[0].FalseStatements);
    }else{
      barId = 'trueBar_' + i;
      Alert.render(d3.select(this).data()[0].TrueStatements);
    }
    d3.select(this).attr('id', barId);
  })
  .attr("transform", function (d) {
    return "translate(" + x0(d.TestSuite) + ",0)";
});

在任何情况下,这都会为每个栏分配一个唯一的ID(即“bar_25”或“falseBar_14”),为您提供识别每个栏的理想方式。

编辑:在OP向我展示他们正在使用的实际代码之后,以下是我对解决方案的建议(实际上与上面的代码在同一行)。

您实际应该修改的代码是您发布的代码下面的代码。它是渲染实际条形的地方:

state.selectAll("rect")
  .data(function(d) { return d.ages; })
.enter().append("rect")
  .attr("width", x1.rangeBand())
  .attr("x", function(d) { return x1(d.name); })
  .attr("y", function(d) { return y(d.value); })
  .attr("height", function(d) { return height - y(d.value); })
  .style("fill", function(d) { return color(d.name); });

我建议在每个栏中添加一个id属性如下:

state.selectAll("rect")
  .data(function(d) { return d.ages; })
.enter().append("rect")
  .attr("width", x1.rangeBand())
  .attr("id", function(d, i) {return 'bar_' + i}) // <-- Edited line
  .attr("x", function(d) { return x1(d.name); })
  .attr("y", function(d) { return y(d.value); })
  .attr("height", function(d) { return height - y(d.value); })
  .style("fill", function(d) { return color(d.name); });

您必须了解为什么这个,而不是您最初提供的代码块是相关的。如你所说,第一个块渲染每组条形(因此append("g")代表svg组)。第二个块以append("rect")开头,表示svg矩形。这个和其他行(即样式(“填充”)...,attr(“x”)...和attr(“y”)......)清楚地表明这个块是处理实际条形的块而不是团体。