Home > OS >  how can i add text label on y-axis in bar chart d3.js
how can i add text label on y-axis in bar chart d3.js

Time:11-08

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

enter image description here

this is what i have implemented enter image description here

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

  • Related