ptk
ptk

Reputation: 7653

Can't set the number of ticks on time-based x-axis to custom amount for bar chart

I'm currently using the following code to set the number of ticks on my time-based x-axis to 5; however, every single tick continues to display regardless of what number I insert within "ticks()".

The code I'm using to set the number of ticks to 5

let xAxisLower = d3.axisBottom(x)
        .ticks(5)
        .tickFormat(d3.timeFormat("%m-%d"))
        .tickPadding(15);

How do I set the number of ticks on the x-axis to 5 and why can't I do so with .ticks(5)?

The JavaScript code (refer to JSFiddle for further detail)

tradeArr = [
    {date: "2017-06-15" , bps: 0},
    {date: "2017-06-14" , bps: 0},
    {date: "2017-06-13" , bps: 0},
    {date: "2017-06-12" , bps: 0},
    {date: "2017-06-09" , bps: 0},
    {date: "2017-06-08" , bps: 0},
    {date: "2017-06-07" , bps: 0},
    {date: "2017-06-06" , bps: 0},
    {date: "2017-06-05" , bps: 0},
    {date: "2017-06-02" , bps: 0},
    {date: "2017-06-01" , bps: 13.9},
    {date: "2017-05-31" , bps: 0},
    {date: "2017-05-30" , bps: 0},
    {date: "2017-05-29" , bps: 0},
    {date: "2017-05-26" , bps: 0},
    {date: "2017-05-25" , bps: 0},
    {date: "2017-05-24" , bps: 0},
    {date: "2017-05-23" , bps: 0},
    {date: "2017-05-22" , bps: 0},
    {date: "2017-05-19" , bps: 0},
    {date: "2017-05-18" , bps: 0},
    {date: "2017-05-17" , bps: 0},
    {date: "2017-05-16" , bps: 1.95},
    {date: "2017-05-15" , bps: 0},
    {date: "2017-05-12" , bps: 0}
];

tradeArr.forEach(obj => {
    obj.date = d3.timeParse("%Y-%m-%d")(obj.date);
})

generateBarChart(tradeArr);

function generateBarChart(data) {
    console.log(data);

    // chart configuration
    let margin = {
        top: 20,
        right: 20,
        bottom: 30,
        left: 50
    };

    let width;
    let height;

    let x = d3.scaleBand()
        .domain(data.map(function(d) { return d.date; }));

    let y = d3.scaleLinear()
        .domain([d3.min(data, function(d) { return d.bps; }), d3.max(data, function(d) { return d.bps; })])

    let xAxisLower = d3.axisBottom(x)
        .ticks(5)
        .tickFormat(d3.timeFormat("%m-%d"))
        .tickPadding(15);

    let yAxis = d3.axisLeft(y)
        .ticks(2)
        .tickSize(0)
        .tickPadding(15);

    let svg = d3
        .select("#price-chart-graph")
            .style("position", "relative") // strictly for the tooltip
        .append("svg") // append an svg to the div
            .style("overflow", "hidden")
            .style("position", "relative");

    let artboard = svg
                    .append("g")
                        .attr("transform", "translate(" + margin.left + ", " + margin.right + ")");

    let xAxisLowerEl = artboard.append("g") // x-axis
        .attr("class", "x-axis")
        .style("font-size", "14px");

    let yAxisEl = artboard.append("g") // y-axis
        .attr("class", "y-axis")
        .style("font-size", "14px");

    let bars = artboard.selectAll(".bar")
                    .data(data)
                    .enter().append("rect")
                    .style("fill", "black")

    function drawChart() {
        width = parseInt(d3.select("#price-chart-graph").style("width")) - margin.left - margin.right;
        height = parseInt(d3.select("#price-chart-graph").style("height")) - margin.top - margin.bottom;

        svg.attr("width", width + margin.left + margin.right) // give it width
        svg.attr("height", height + margin.top + margin.bottom) // give it height

        x.rangeRound([0, width], .05).padding(0.1);
        y.range([height, 0]);
        // call new x axis
        xAxisLowerEl.attr("transform", "translate(0," + height + ")").call(xAxisLower);
        yAxisEl.call(yAxis);

        bars
            .attr("x", function(d) { return x(d.date); })
            .attr("width", function(d) { return x.bandwidth()})
            .attr("y", function(d) { return y(d.bps); })
            .attr("height", function(d) { return height - y(d.bps); })

    }

    drawChart();

    window.addEventListener('resize', drawChart);
}

Upvotes: 1

Views: 712

Answers (1)

Chris Applegate
Chris Applegate

Reputation: 762

Your x-axis is of type scaleBand, and ticks() doesn't work on banded axes. From the documentation:

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

You can however explicitly set the values with tickValues(), so you can try filtering the domain down to five values and setting manually. This may get you in the right direction:

let tickInterval = 5;
let tickValues = data.map(function(d) { return d.date; }).filter(function(d, i) { return i % tickInterval === 0 });
let xAxisLower = d3.axisBottom(x)
    .tickFormat(d3.timeFormat("%m-%d"))
    .tickValues(tickValues)
    .tickPadding(15);

You might need to tweak tickInterval to fit the length of your data, but that should be a start.

Upvotes: 2

Related Questions