b-ryce
b-ryce

Reputation: 5828

d3.js ticks values not working as expected

I'm a d3 noob. I have a chart that looks close to what I want. enter image description here

Right now the xlabels for years are all hard coded. Like this:

.call(d3.axisBottom(xScale)
                .ticks([1850, 1900, 1950, 2000]));

However I want to update the tick marks to be dynamic so labels show up every 5 years or so and I don't need to hard code those in.

Here is what my code looks like:

<body>
<div id="container" class="svg-container"></div>
<script>

//--------------------------PREPARATION--------------------------//
//------------------------SVG PREPARATION------------------------//
var width = 960;
var height = 500;
var margin = 5;
var padding = 5;
var adj = 20;
// we are appending SVG first
var svg = d3.select("div#container").append("svg")
.attr("preserveAspectRatio", "xMinYMin meet")
//.attr("viewBox", "-20 -20 1600 1600")
.attr("viewBox", "-" + adj + " -"+ adj + " " + (width + adj) + " " + (height + adj*2))
.style("padding", padding)
.style("margin", margin)
.classed("svg-content", true);

//-----------------------SCALES PREPARATION----------------------//
var xScale = d3.scaleBand()
    .rangeRound([0, width])
    .paddingInner(0.05);
var yScale = d3.scaleLinear()
    .rangeRound([height, 0]);

//------------------------DATA PREPARATION-----------------------//
var dataset = d3.csv("q3.csv");
dataset.then(function(data) {
    data.map(function(d) {
            d.running_total = +d.running_total;
            return d;});
});

dataset.then(function(data) {
    xScale.domain(data.map(function(d) {return d.year}))
    yScale.domain([0, d3.max(data, function(d)
                             {return d.running_total; })]);
});

console.log(dataset);


dataset.then(function (data) {
    svg.selectAll("div")
    .data(data)
    .enter().append("rect")
    .attr("class", "bar")
    .attr("x", function(d){
        return xScale(d.year);
    })
    .attr("y", function (d) {
        return yScale(d.running_total);
    })
    .attr("width", xScale.bandwidth())
    .attr("height", function (d) {
        return height - yScale(d.running_total);
    });
    svg.append("g")
    .attr("class", "axis")
    .attr("transform", "translate(0," + height + ")")
    .call(d3.axisBottom(xScale)
            .ticks([1850, 1900, 1950, 2000]));

    svg.append("g")
        .attr("class", "axis")
        .call(d3.axisLeft(yScale));
});

</script>
</body>

I tried setting the ticks to how many labels I want like this: .ticks(50) but that didn't work (all the labels showed up)

svg.append("g")
    .attr("class", "axis")
    .attr("transform", "translate(0," + height + ")")
    .call(d3.axisBottom(xScale)
            .ticks(50));

Upvotes: 1

Views: 1629

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102174

The API explains your issue: axis.ticks() has no effect with a band scale.

This method has no effect if the scale does not implement scale.ticks, as with band and point scales. (emphasis mine)

Therefore, what you can do for having one label every 5 years is filtering the scale's domain:

.call(d3.axisBottom(xScale).tickValues(xScale.domain().filter(function(_, i) {
  return !(i % 5);
})));

Upvotes: 5

Related Questions