I would like to display text on y-axis tick point they are like always same even if data changed here are the tick point text ["Low" , "Medium" , "High"]
i have tried a lot but im unable to find the perfect solution
tick points are alway 3 and they have to show this text on each tick point ["Low" , "Medium" , "High"]
here is the image that how i want
this is what i have implemented
im unable to set the text of ["Low" , "Medium" , "High"]
by replacing [5, 10, 15]
here is the array of data for plotting graph
[
{ group: 'A', value: 5 },
{ group: 'B', value: 15 },
{ group: 'C', value: 10 },
{ group: 'D', value: 15 },
{ group: 'E', value: 10 },
{ group: 'F', value: 5 },
]
here is the bar chart code
var outerWidth = convertRemToPixels(40),
outerHeight = barGraphContainerRef.current.clientHeight;
var margin = {
top: convertRemToPixels(2),
right: convertRemToPixels(2),
bottom: convertRemToPixels(2),
left: convertRemToPixels(2),
},
width = outerWidth - margin.left - margin.right,
height = outerHeight - margin.top - margin.bottom;
var x = d3.scaleBand().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var xAxis = d3.axisBottom(x);
var yAxis = d3.axisLeft(y).ticks(3);
function make_y_gridlines() {
return d3.axisLeft(y).ticks(3);
}
//Defenining the tooltip div
var chart = d3
.select(refe.current)
.attr('width', outerWidth)
.attr('height', outerHeight);
let tooltip = d3
.select('#root .tooltipContainer')
.style('position', 'absolute')
.style('top', 0)
.style('left', 0)
.style('display', 'none');
var gradient = chart
.select('.lGradient')
.attr('id', 'gradient')
.attr('x1', '0%')
.attr('y1', '00%')
.attr('x2', '0%')
.attr('y2', '100%')
.attr('spreadMethod', 'pad');
gradient
.select('.firstStop')
.attr('offset', '-100%')
.attr('stop-color', '#0170ac')
.attr('stop-opacity', 1);
gradient
.select('.secondStop')
.attr('offset', '100%')
.attr('stop-color', '#013c5d')
.attr('stop-opacity', 1);
var main = chart
.select('.chart')
.attr('transform', 'translate(' margin.left ',' margin.top ')');
main
.select('.x-axis')
.attr('transform', 'translate(0,' height ')')
.call(xAxis)
.style('color', '#a4a4a4');
main
.select('.y-axis')
.attr('transform', 'translate(0,' 0 ')')
.call(yAxis)
.style('color', '#a4a4a4');
y.domain([
0,
d3.max(graphData, function (d) {
return d.value;
}),
]);
x.domain(
graphData.map(function (d) {
console.log(d);
return d.group;
})
).padding([0.5]);
main
.select('.x-axis')
.call(xAxis)
.selectAll('text')
.style('text-anchor', 'end')
.attr('dx', '.3em')
.attr('dy', '1em')
.style('font-size', '.8rem')
.attr('transform', 'rotate(0)')
.style('font-family', '"Roboto", sans-serif');
main
.select('.y-axis')
.call(yAxis)
.selectAll('text')
.attr('class', 'yAxiesText')
.attr('transform', 'rotate(-90)')
.attr('y', '-2em')
.attr('x', '.4em')
.attr('dy', '.71em')
.style('font-size', '.8rem')
.style('text-anchor', 'end')
.style('font-family', '"Roboto", sans-serif');
main
.select('.gridder')
.call(make_y_gridlines().tickSize(-width).tickFormat(''))
.attr('id', 'gridSystem');
var rects = main.selectAll('.paths').data(graphData.map(e => e.value));
const names = graphData.map(e => e.group);
rects
.join('path')
.attr('class', 'paths')
.attr('d', function (d, i) {
return RectangleBarWithRadiusOneSide(
x(names[i]),
y(d),
x.bandwidth(),
height - y(d),
5 // radius
);
})
here is the RectangleBarWithRadiusOneSide
function for making onside border radius
const RectangleBarWithRadiusOneSide = (x, y, width, height, radius) => {
return (
'M'
(x radius)
','
y
'h'
(width - 2 * radius)
'a'
radius
','
radius
' 0 0 1 '
radius
','
radius
'v'
(height - 2 * radius)
'v'
radius
'h'
-radius
'h'
(2 * radius - width)
'h'
-radius
'v'
-radius
'v'
(2 * radius - height)
'a'
radius
','
radius
' 0 0 1 '
radius
','
-radius
'z'
);
};
here is the convertRemToPixels
function
export const convertRemToPixels = rem => {
return rem * parseFloat(getComputedStyle(document.documentElement).fontSize);
};
I hope i have explained meaningfully
if i get any solution from the anyone that is so appreciatable
thanks advance!
CodePudding user response:
You can use the tickFormat()
function on a d3 axis generator to format the tick values. Create a scale to map the data values to your "Low", "High", "Medium" labels and pass it to tickFormat()
:
const tickScale = d3.scaleOrdinal()
.domain([...new Set(data.map(d => d.value))].sort(d3.ascending)) // keep unique values in ascending order
.range(["Low", "Medium", "High"])
.unknown(""); // other values are not displayed
const yAxis = d3.axisLeft(sy)
.ticks(3)
.tickFormat(tickScale);
A working prototype can be found here: https://codepen.io/ccasenove/pen/abKNOqa