How to include additional lines between x-axis values using d3.js? - d3.js

I created x axis with the values ​​and the labels and applied a style in grid lines. The code is below:
let xScale = d3.scalePoint().domain(axisXValues).range([0, width]);
let xAxisGenerator = axisXLabels.length > 0
? d3.axisBottom(xScale).ticks(axisXValues.length).tickFormat((d,i) => axisXLabels[i])
: d3.axisBottom(xScale).ticks(axisXValues.length);
chart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxisGenerator.tickSize(-height));
I would like to include more ticks between (green) the values ​​and apply a different style as in the example below:
Does anyone have an idea?
Thanks!

I would add a new linear scale with the same range and domain in the original point scale. (Keeping the original point scale and its rendered axis, of course)
Then calculate the values in between and plot the axis using axisBottom.tickValues()
Color of the tick line can be changed by accessing .tick line and applying the stroke attribute.
Do note that this would only work if the point scale's domain is equally spaced, i.e. linear.
Adding the following code to yours should work. Attaching a working codepen too.
const xScaleInBetween = d3.scaleLinear()
.range(xScale.range())
.domain(d3.extent(axisXValues));
let xTicks = xScale.domain();
let xTicksInBetween = Array.from({length: xTicks.length - 1},
(_, j) => ((xTicks[j] + xTicks[j+1]) /2));
chart.append("g")
.attr("class", "x-axis-between")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScaleInBetween)
.tickValues(xTicksInBetween)
.tickSize(-height))
.call(g => g.selectAll('.tick line').attr('stroke', 'green'))
.call(g => g.selectAll('.tick text').remove())

Related

D3.js V4 : How to create X axis with time and %H:%M:%S format

I am trying to create a chart with X axis that shows timely progress of a trade with %H:%M:%S format.
I have tried following code but it shows years only. The seconds are very important to show on the x axis. I know timeParse needs to be used but I am not sure how to leverage it. I have searched a lot online but no examples.
// Add X axis
var parseDate=d3.timeParse("%H:%M:%S")
var x = d3.scaleTime()
.domain([new Date(0,0,0), new Date (12,59,59)])
.range([ 0, width ]);
You would need the following:
The desired scale.
var x = d3.scaleTime()
.domain([new Date(1554236172000), new Date(1554754572000)])
.range([0, width]);
The axis with the correct format and the number of desired ticks, you may want to use .ticks(d3.timeMinute.every(desiredMinutesToHandle)); for a better display of your data.
var xAxis = d3.axisBottom(x)
.tickFormat(d3.timeFormat("%H:%M:%S"))
.ticks(50);
Finally append your axis to your svg with certain transformations to have a nice look
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.attr("y", -5)
.attr("x", 30)
.attr("transform", "rotate(90)")
Plunkr with working code

D3JS: unable to set only 5 ticks in x Axis

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.

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 produce axes that do not intersect at (0, 0)?

I would like to generate axes that do not intersect at (0, 0) (and also do not necessarily coincide with the edges of a plot), as shown in the example below.
How can I do this with d3?
You will first need to figure out where you want to display the axis. If they are fixed to canvas, take ratios of width and height.
Here's an example that I made:
http://vida.io/documents/zB4P4fjHz79um3qzX
x-axis is at to 2/3 of height:
.attr("transform", "translate(0," + height * 2 / 3 + ")")
And y-axis is at 1/3 of width:
.attr("transform", "translate(" + width / 3 + ", 0)")
If you need the axis relative to range of values, calculate them based on range. For example:
var domain = d3.extent(data, function(d) { return d.y_axis; })
var y_axis_pos = width * (y_axis_value - domain[1]) / (domain[0] - domain[1]);
// svg code...
.attr("transform", "translate(" + y_axis_pos + ", 0)")
From the D3.js API documentation:
to change the position of the axis with respect to the plot, specify a transform attribute on the containing g element.

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