I have an array similar to this:
[{year: 1999, val: 5}, {year: 2002, val: 8}]
and I would like to add an axis where I have one tick for each year value (something I can do with tickValues and tickFormat) but where the tick label is not only the year but has a custom format, so the result could be something like "1999: 5" for the first array element.
To rephrase it:
Where I'm now
const xAxis = d3.axisTop(xScale)
.tickValues(data.map(d => d.year);
This is not ok because only the year is visualized on the label of the tick and I would like to use a custom format.
Is this possible with d3?
I have an array similar to this:
[{year: 1999, val: 5}, {year: 2002, val: 8}]
and I would like to add an axis where I have one tick for each year value (something I can do with tickValues and tickFormat) but where the tick label is not only the year but has a custom format, so the result could be something like "1999: 5" for the first array element.
To rephrase it:
Where I'm now
const xAxis = d3.axisTop(xScale)
.tickValues(data.map(d => d.year);
This is not ok because only the year is visualized on the label of the tick and I would like to use a custom format.
Is this possible with d3?
Share Improve this question edited Jul 2, 2017 at 14:52 heapOverflow asked Jul 2, 2017 at 14:48 heapOverflowheapOverflow 1,2853 gold badges21 silver badges35 bronze badges3 Answers
Reset to default 15You could try like this
const xAxis = d3.axisTop(xScale)
.tickValues(data)
.tickFormat(d => (d.year +":"+ d.val));
Since you didn't show the scale in your question we don't know what type of scale you have and what are the domain values. But one thing is sure: you cannot pass the whole object to it. Therefore, your tickFormat
doesn't have access to one of the properties in each object.
A simple solution is using the index of the tick to get the other property, provided that you are displaying all the ticks (and that you are using an ordinal scale):
var axis = d3.axisBottom(scale)
.tickFormat(function(d, i) {
return d + ": " + data[i].val;
});
Here is a demo:
var svg = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 100);
var data = [{
year: 1999,
val: 5
}, {
year: 2002,
val: 8
}, {
year: 2005,
val: 1
}, {
year: 2008,
val: 4
}, {
year: 2011,
val: 9
}, {
year: 2014,
val: 2
}];
var scale = d3.scalePoint()
.range([20, 480])
.domain(data.map(function(d) {
return d.year
}));
var axis = d3.axisBottom(scale)
.tickFormat(function(d, i) {
return d + ": " + data[i].val;
});
var gX = svg.append("g")
.attr("transform", "translate(0,50)")
.call(axis);
<script src="https://d3js/d3.v4.min.js"></script>
What I have been able to do now:
d3.axisTop(xScale)
.tickValues(data.map(d => d.year))
.tickFormat((d, i) => data[i].val);
Quite ugly but it works. If I get a better solution I will accept a different one.