In the original bullet.js
from the bostock example https://bl.ocks.org/mbostock/4061961
Instead of getting the ticks from the scale you get the values from the range, measure and mark
change around line 109
// var tickVals = x1.ticks(8);
var tickVals = rangez.concat(measurez).concat(markerz);
// Update the tick groups.
var tick = g.selectAll("g.tick")
.data(tickVals, function(d) {
return this.textContent || format(d);
});
Edit
There is a problem if you update the data based on a new fetch from the server. some of the ticks end up on the wrong location. If the number of markers,measures,ranges also change they also end up at the wrong location.
It depends on the selection you supply to the bullet call.
The confusion is caused by the poor naming of the main program.
var svg = d3.select("body").selectAll("svg")
.data(data)
.enter().append("svg")
.attr("class", "bullet")
.attr("width", svgWidth)
.attr("height", svgHeight)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(chart);
The name suggests that svg
is a selection of svg
elements. This is incorrect, it is a selection of g
elements.
The update()
function should reflect this
function updateData() {
d3.json("mailboxes.json", function (error, data) {
d3.select("body")
.selectAll("svg")
.select('g')
.data(data)
.call(chart.duration(500));
});
}
If the number of bullet graphs changes on the update there is the problem that they are not created or deleted if needed. So we need to make a function that can be used for initial and update calls.
function drawCharts() {
d3.json("mailboxes.json", function (error, data) {
var svg = d3.select("body").selectAll("svg").data(data);
svg.exit().remove();
svg.enter().append("svg")
.attr("class", "bullet")
.attr("width", svgWidth)
.attr("height", svgHeight)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.select("body")
.selectAll("svg")
.select('g')
.data(data)
.call(chart.duration(500));
});
}
A better change in bullet.js [109] would be:
// var tickVals = x1.ticks(8);
var tickVals = [];
rangez.concat(measurez).concat(markerz).forEach(e => {
if (tickVals.indexOf(e) == -1) tickVals.push(e);
});
// Update the tick groups.
var tick = g.selectAll("g.tick").data(tickVals);
That is do not use the value of the tick to match, in case we have multiple values in the ticks, and remove the duplicates.
We also need to change the update of the ticks, about 30 lines down
tickUpdate.select("text")
.attr("y", height * 7 / 6);
to
tickUpdate.select("text")
.text(format)
.attr("y", height * 7 / 6);