2016-02-14 66 views
0

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

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”,这已经在data.using 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'); 
 
}

+2

click事件回调可以带两个参数,第一个参数对应于绑定到clicked元素的数据。尝试像'.on(“click”,function(d,i){console.log(d);})''看看这是否是你正在寻找的数据 –

+0

@Hugues Stefanski - 我编辑我的问题很少多一点。 '.on(“click”,function(d,i){console.log(d);})'包含我需要显示的数据,但是如何唯一地标识小节? –

回答

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); }); 

重要的是,你明白为什么这个,而不是你最初提供的代码块是相关的。正如你所说,第一个块呈现每组条(因此代表svg组的append("g"))。第二个块从append("rect")开始,这意味着svg矩形。这个和其他行(即样式(“填充”)...,attr(“x”)...和attr(“y”)...)清楚地表明这个块是处理实际条而不是团体。

+0

你能告诉我,你在给定的代码中是什么意思? –

+0

@DesiDelite是的,每个元素可能包含一个'id'属性,因此它可以被唯一标识。重要的是不要将其分配给代码中的任何其他元素。下面是如何使用它们的另一个很好的例子:http://stackoverflow.com/questions/13188395/setting-an-id-issue-in-d3 我的意思是我的答案(如果我不是,我很抱歉明确的)是id的主要用例正是你在这里呈现给我们的问题,这是需要唯一标识一个元素。 –

+0

你能编辑我的代码并更新你的答案吗? –