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.
Related
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.
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
I am using d3.js for scatter plot,I want to plot x and y axis such that they intersect at point(100,75).how to do this?
I am using
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + (padding+223) + ")")
.call(xAxis2);
//Create Y2 axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + (padding+200) + ",0)")
.call(yAxis2);
But this will not change according to the scale,and I have used variable for scale.
Please let me know if you need more information.
You would need to offset the axes by the respective amount, which you can determine using the scales of the axes, i.e.
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + yScale(75) + ")")
.call(xAxis2);
and similarly for the y axis. You may have to tweak the offset slightly to account for other offsets, labels etc.
The following is my draw axis code:
var seasons = ["summer", "winter", "fall", "spring"];
var margin = {top:80, right:30, bottom:30, left:30},
width = 1200 - margin.right - margin.left,
height = 800 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.domain(seasons)
.rangeRoundBands([0, width], 0.9);
xAxis = d3.svg.axis()
.scale(x)
.tickSize(4, 6)
.tickPadding(6)
.orient("bottom");
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
</script>
However, the tickPadding function does now introduce a space between the ordinal axis categories.
More specifically, I want that each of the summer, winter, fall and spring parts of the axis are separate from each other, sort of like dashed line. How can I get this?
I don't know of any way built into the d3 axis to accomplish this, but you can remove the path it draws and replace it with a dashed line, like so:
// Draw the axis, as you currently are
var axisElem = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Remove the line
axisElem.selectAll("path.domain").remove();
// Figure out how big each dash should be
var gapFraction = 0.1; // The portion of the line that should be a gap
var total = x(seasons[1]) - x(seasons[0]);
var dash = total * (1 - gapFraction);
var gap = total * gapFraction;
// Draw the dashed line
axisElem.append("line")
.classed("domain", true)
.attr("x1", x(seasons[0]) - dash / 2 + gap / 2)
.attr("x2", x(seasons[seasons.length - 1]) + dash / 2 - gap / 2)
.attr("y1", 0)
.attr("y2", 0)
.attr("stroke", "black")
.attr("stroke-dasharray", dash + "," + gap);
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.