D3JS: unable to set only 5 ticks in x Axis - d3.js

I've been unable to set only 5 ticks on my x Axis, by default it set 10 ticks, multiples of 5, I tried to use ´.ticks(5)´ but it's not working for me. If if visualize the chart on mobile, 10 ticks becomes almost unreadable. But as I mentioned ´.ticks(5)´ it's not working
this is the snippet which draws the x axis:
var xAxis = svg.append("g")
.style("font-size", textSetter())
.attr("class", "xAxis", "axis")
.attr("transform", "translate(" + 0 + "," + heightTwo + ")")
.call(d3.axisBottom(xScale).ticks(5)
.tickPadding(5).tickFormat(d => d + "%"))
How can I solve this? Thanks

You could set all the text in the axis to a particular class and then hide the ticks based on the number for example.
//Create the xAxis and assign x-axisticks class to the tick text
var xAxis = svg.append("g")
.style("font-size", textSetter())
.attr("class", "xAxis", "axis")
.attr("transform", "translate(" + 0 + "," + heightTwo + ")")
.call(d3.axisBottom(xScale)
.selectAll('text')
.attr('class', 'x-axisticks');
//remove the ticks which based on the multiples
var xticks = d3.selectAll('.x-axisticks');
xticks.attr('class', function (d, i) {
i = i + 1;
if (i % 5 !== 0) d3.select(this).remove();
});
Hope this helps. A more specific use-case answer would probably require some more code to be posted from your end so that I can tailor an answer, but this should work.

Related

D3 - Position second x axis labels

I have a stackblitz here - https://stackblitz.com/edit/d3-stacked-trend-bar-positioned-months-1b93nz?file=src%2Fapp%2Fbar-chart.ts
I have a stacked bar chart using D3 in Angular.
I'm trying to position a second axis of labels on the x axis.
Currently I'm using the with of the graph but this means the labels dont line up correctly with the bars.
Is there a better D3 way to add these labels and positino them.
Use the x-position of the bars and position the text in the middle of it.
private drawBarTitle(data:any){
this.chart.append('g')
.attr("transform", "translate(" + 10 + "," + (this.height+10) + ")")
.selectAll('g')
.data(data)
.enter()
.append('g')
.attr('transform', (d:any, i:any)=>{
var x = this.x(d.date) + (i%2) * 0.525 * this.x.bandwidth();
return "translate(" + (x + this.x.bandwidth()*0.95*0.25) + "," + 0 + ")"
})
.append('text')
.text((d:any, i:any)=>{ return d.type; })
.attr("dy", "-0.3em")
.classed('trend-type', true)
.style("text-anchor", "end")
.attr("transform", "rotate(-90)");
}

Cut off gridline at the end in d3.js

I'd like to cut off the grid line at the end of the graph. If I remove the padding in xScale, then the end tick "2016"'s "16" will be cut off.
Which part should I fix, yScale, xScale, or the gridline?
//Define X axis
xAxis = d3.axisBottom()
.scale(xScale)
.ticks(10)
.tickFormat(formatTime);
//Define Y axis
yAxis = d3.axisLeft()
.scale(yScale)
.ticks(5);
//Define Y axis gridlines
function make_y_gridlines() {
return d3.axisLeft(yScale)
}
//Create axes
svg.append("g")
.attr("class", "axis x")
.attr("transform", "translate(0," + (h - padding) + ")")
.call(xAxis);
svg.append("g")
.attr("class", "axis y")
.attr("transform", "translate(" + padding + ",0)")
.call(yAxis);
// add the Y gridlines
svg.append("g")
.attr("class", "grid")
.attr("transform", "translate(" + padding + ",0)")
.call(make_y_gridlines()
.tickSize(-w)
.tickFormat("")
)
As the x-axis is defined with:
.range([padding, w - padding * 2])
This means, the graph begins at 1 * padding from the left of the svg container and ends at width - 2 * padding from the left. Which means the width of the graph (as opposed to the width of the svg container) is width - 3 * padding.
Thus the actual size of the y grid lines should be width - 3 * padding.
In the code, this means that you can just replace the ticksize in the definition of the y gridlines:
.tickSize(-w)
with:
.tickSize(-w + 3*padding)
It's -(w-3*padding) since the ticks by default are going to the left of the y axis and here we want them to the right.

D3 alignment of gridline for x and y axis

I am currently facing problem in setting grid line for a graph.
Problem
i) x grid line is not aligned to the x-axis
ii)y grid line is not appearing.
The code and output are in the
Plunker
Anyone can guide me on this? thanks in advance.
i) x grid line is not aligned to the x-axis
Reason:
You are doing like this
.attr("transform", "translate(0," + height + ")")
It should have been like this:
.attr("transform", "translate("+margin.left + "," + (height+ margin.top) + ")")
So you missed the margin left and margin top given to the graph, please add them as shown above.
ii)y grid line is not appearing.
Reason:
svg.append("g")
.attr("class", "grid")
.call(ygridlines <--- this is a function
.tickSize(-width)
.tickFormat("")
)
it should have been
svg.append("g")
.attr("class", "grid")
.attr("transform", "translate("+margin.left + "," + (margin.top) + ")")
.call(ygridlines()
.tickSize(-width)
.tickFormat("")
)
Also you missed the transform for the y axis.
Working code here

How to draw vertical text as labels in D3

I'm trying to draw vertical labels for the heatmap that I'm working. I'm using the example from http://bl.ocks.org/tjdecke/5558084. Here is the part of the code that I've changed:
var timeLabels = svg.selectAll(".timeLabel")
.data(ife_nr)
.enter().append("text")
.text(function(d) {
return d;
})
.attr("x", function(d, i) {
return (i * gridSize);
})
.attr("y", 0)
//.style("text-anchor", "middle")
//.attr("transform", "translate(" + gridSize / 2 + '-5' + ")")
.attr("transform", "translate(" + gridSize/2 + '-8' + "), rotate(-90)")
.attr("class", function(d, i) {
return ((i >= 0) ? "timeLabel mono axis axis-worktime" : "timeLabel mono axis");
});
But it appears the labels seems to be stacked on top one another on top of the first grid. How can I edit this code to get the labels correctly displayed?
Two problems: first, the translate should have a comma separating the values:
"translate(" + gridSize/2 + ",-8), rotate(-90)")
Assuming that -8 is the y value for the translate. If you don't have a comma, the value inside the parenthesis should be just the x translation (If y is not provided, it is assumed to be zero). But even if there is actually no comma and all that gridSize/2 + '-8' is just the x value you still have a problem, because number plus string is a string. You'll have to clarify this point.
Besides that, for rotating the texts over their centres, you'll have to set the cx and cy of the rotate. Have a look at this demo:
var svg = d3.select("body")
.append("svg")
.attr("width", 400)
.attr("height", 100);
var texts = svg.selectAll(".texts")
.data(["foo", "bar", "baz"])
.enter()
.append("text");
texts.attr("y", 50)
.attr("x", function(d,i){ return 50 + 80*i})
.text(function(d){ return d});
texts.attr("transform", function(d,i){
return "rotate(-90 " + (50 + 80*i) + " 50)";
});
<script src="https://d3js.org/d3.v4.js"></script>

d3 axis tick alignment

I have a d3 bar chart with, and the axis tick marks are centered below the bars (as I would expect). In this case, I would actually like to left align the axis ticks and have the ticks under the left edge of the bar. Is that possible?
EDIT: Javascript for constructing the axis
// note width is just the width of the chart
var xScale = d3.scale.ordinal().rangeRoundBands([0,width], .1);
var xAxis = d3.svg.axis().scale(xScale).orient("bottom");
here is an example of left aligning the ticks.
http://bl.ocks.org/mbostock/6186172
the idea is that after you create the ticks you collect them and aligne them:
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.attr("y", 6)
.attr("x", 6)
.style("text-anchor", "start");
Why not just create a new scale?
var padding = .1;
var axisScale = d3.scale.linear()
.domain([0, n])
.range([0 + padding, WIDTH + padding]);
Where n is the number of bars in your histogram.
I think that this should be adjusted when you add the axis to your graph.
Try (assuming your graph is called svg):
var bandSize = xScale.rangeBand();
svg.append("svg:g")
.attr("transform", "translate(-" + bandSize + "," + h + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "start")
.attr("transform", "translate(" + bandSize + ", 0)");
In my experiments, this shifts the ticks to the start of each band, and retains the text centered under each band.

Resources