d3 show labels only for ticks with data in a bar chart

故事扮演 提交于 2019-12-01 07:04:13

问题


First, I'm new with D3. :) I have a stacked bar chart. My y axis is a ordinal scale (state). In my data, I could have total=0 for some ticks. So, I just want to see the labels when the total > 0 but maintain all the ticks of the data.

var data = [{ "state":"A", "total":"10"},
{ "state":"B", "total":"0"},
{ "state":"C", "total":"0"},
{ "state":"D", "total":"20"},
{ "state":"E", "total":"0"},
{ "state":"F", "total":"50"}]

I've tried this code, but this remove all the ticks with total = 0. I just want to remove the label of that tick.

yAxis.tickValues(dataSet.map( function(d,i) 
    { 
        if (d.total > 0)
            return d.state; 
        else
            if(i % 4 === 0 ) return d.state; 
    })
    .filter(function (d) 
    { return !!d; } )); 

Thanks, Filipe

UPDATE Here is the code:

    <!DOCTYPE html>

    <html xmlns="http://www.w3.org/1999/xhtml" class="ocks-org do-not-copy">
    <head>
      <link rel="stylesheet" type="text/css" href="style.css" />
    </head>
    <body>
    <div id="timeLine"></div>
    <!--style>

    svg {
            font: 10px sans-serif;
        }

    path {
        fill: steelblue;
    }

    .axis path,
    .axis line {
        fill: none;
        stroke: #000;
        shape-rendering: crispEdges;
    }
</style-->
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var timeline;
var labels;


    var margin = {
        top : 20,
        right : 10,
        bottom : 60,
        left : 80
    },
    width = 500 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

    var x = d3.scale.linear()
        .rangeRound([0, width]);

        var y = d3.scale.ordinal()
        .rangeBands([height, 0], 0.1);

    var color = d3.scale.ordinal()
        .range(["#1f77b4", "#2ca02c", "#E53524"]);
    //var color = d3.scale.category10()

    var xAxis = d3.svg.axis()
        .scale(x)
        .orient("bottom")
        .tickFormat(d3.format(".2s"))
        .ticks(10);

    var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left")
        .ticks(5);

    timeline = d3.select("#timeLine").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")")

    var dataSet;
    var all_nodes_t;
    var all_updates_t;
    var test;
    var entity = "ALL";

    dataSet = [
    { "Date":"2014-01", "insert":"27", "remove":"17","updates":"427"},
    { "Date":"2014-02", "insert":"27", "remove":"17","updates":"427"},
    { "Date":"2014-03", "insert":"27", "remove":"17","updates":"427"},
    { "Date":"2014-04", "insert":"0", "remove":"0","updates":"0"},
    { "Date":"2014-05", "insert":"27", "remove":"17","updates":"427"},
    ];
        color.domain(d3.keys(dataSet[0]).filter(function (key) {
            return key !== "Date";
        }));

    dataSet.forEach(function (d) {
        var x0 = 0;
        d.ages = color.domain().map(function (name) {
                return {
                    name : name,
                    x0 : x0,
                    x1 : x0 += +d[name]
                };
            });
        d.total = d.ages[d.ages.length - 1].x1;
    });

    //HERE
    yAxis.tickFormat(dataSet.map(function(d) { 
        d.total == 0 ? "" : d.Date; 
    }));

    y.domain(dataSet.map(function (d) {
        return d.Date;
    }));

    x.domain([0, d3.max(dataSet, function (d) {
        return (d.total + 5);
    })]);

    timeline.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis)
    .append("text")
    .attr("x", 1)
    .attr("dx", "42em")
    .attr("dy", "3em")
    .style("text-anchor", "end")
    .text("Operations");

    timeline.append("g")
    .attr("class", "y axis")
    .call(yAxis);

    var layer = timeline.selectAll(".state")
        .data(dataSet)
        .enter().append("g")
        .attr("class", "rect")
        .attr("transform", function (d) {
            return "translate(0," + y(d.Date) + ")";
        });

    var rect = layer.selectAll("rect")
        .data(function (d) {
            return d.ages;
        })
        .enter().append("rect")
        .attr("class", "rect")
        .attr("width", 0)
        .attr("x", width)
        .attr('y', function (d, i) {
                return y(d.Date);
            })
        .attr("height", y.rangeBand())
        .style("fill", function (d) {
            return color(d.name);
        });

    rect.transition()
    .duration(600)
    .delay(function (d, i) {
        return i * 300;
    })
    .attr("width", function (d) {
        return x(d.x1) - x(d.x0);
    })
    .attr("x", function (d) {
        return x(d.x0);
    });

</script>
</body>
</html>

回答1:


You can use .tickFormat() to suppress the labels for those particular values. As the thing you want to check isn't part of the data that's available to the scale, you'll need to find it in your entire data:

yAxis.tickFormat(function(d) {
    var val = 0;
    dataSet.forEach(function(item) {
        if(item.Date == d) val = item.total;
    });
    return val == 0 ? "" : d;
});

This will suppress the label (return "") if the total is 0 or the value can't be found in the data set. Complete demo here.



来源:https://stackoverflow.com/questions/28299330/d3-show-labels-only-for-ticks-with-data-in-a-bar-chart

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!