Tobi Oetiker
Tobi Oetiker

Reputation: 5460

d3.js how to place custom labels on horizontal log scaled axis

I am drawing a chart with d3.js using d3.scale.log for the x axis in combination with a custom labels. Unfortunately the labels run into each other ... any hints on how to make this work?

var width = 400;
var x = d3.scale.log().domain([1, 1000]).range([0, width]);

var formatSi = d3.format(".4s");
var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom")
    .tickFormat(function(d, i) {
        return formatSi(d) + 'Hz'
    });

var svg = d3.select("#chart")
    .append("svg").attr("width", width)
    .attr("height", 200)
    .append("g").attr("transform", "translate(20,20)");

([1, 3, 6, 9]).forEach(function(d) {
    x.domain([1, Math.pow(10, d)]);
    svg.append("g").attr("class", "axis x")
        .attr("transform", "translate(0," + d * 2 + "0)")
        .call(xAxis);
});​

A working example of this code is on jsfiddle

Upvotes: 2

Views: 5813

Answers (1)

Tobi Oetiker
Tobi Oetiker

Reputation: 5460

figured it out. Trick is to not use .tickFormat to supply the formatting function, but rather the .ticks method which in turn will apply the supplied formatting function to the .tickFormat method of the scale.

var width = 400;
var x = d3.scale.log().domain([1, 1000]).range([0, width]);

var formatSi = d3.format(".4s");
var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom")
​    .ticks(5,function(d, i) {
        return formatSi(d) + 'Hz';
    });

var svg = d3.select("#chart")
    .append("svg").attr("width", width)
    .attr("height", 200)
    .append("g").attr("transform", "translate(20,20)");

([1, 3, 6, 9]).forEach(function(d) {
    x.domain([1, Math.pow(10, d)]);
    svg.append("g").attr("class", "axis x")
        .attr("transform", "translate(0," + d * 2 + "0)")
        .call(xAxis);
});

The result is still not entirely satisfying as the system seems to have trouble placeing labels when the ticks are close together ...

Upvotes: 6

Related Questions