Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bar chart width (spacing) #621

Open
leineveber opened this issue May 3, 2024 · 2 comments
Open

Bar chart width (spacing) #621

leineveber opened this issue May 3, 2024 · 2 comments

Comments

@leineveber
Copy link

leineveber commented May 3, 2024

Hello, thanks for your package!

I wanted to ask, how should I calculate the bar width and spacing? For example, I have 5 groups of bars. Each group has 5 bars in it.

image

I've added spacing 16 between groups and 2 between bars, bar width - 8 (from the example). It works totally fine, however, if I rotate, it won't resize.

image

I assume it happens since the total sum of width is not filled, like, in MpAndroidChart, the total sum should be "1" - so you should calculate every bar and space and it should give you 1. But how to calculate size here?

For better understanding, I will provide you my code.

to not dive into data manipulations, result data is:

image
import React from 'react';
import {BarChart, barDataItem} from 'react-native-gifted-charts';
import {View} from 'react-native-ui-lib';
import ChartLabel from './ChartLabel';

const data = [
  {
    values: [5, 40, 77, 81, 43],
    label: 'Hemoglobin',
    color: '#7CDE86',
  },
  {
    values: [40, 5, 50, 23, 79],
    label: 'White blood cell',
    color: '#7CD8DE',
  },
  {
    values: [10, 55, 35, 90, 82],
    label: 'Mean corpuscular volume',
    color: '#7C9DDE',
  },
  {
    values: [22, 45, 50, 60, 30],
    label: 'Hematocrit',
    color: '#A17CDE',
  },
  {
    values: [30, 25, 10, 60, 15],
    label: 'Platelet',
    color: '#DC7CDE',
  },
];

const xAxisLabels = ['01.02', '11.02', '19.02', '12.03', '13.03'];

const res: barDataItem[] = [];

for (let i = 0; i < data.length; i++) {
  data.forEach((item, j, array) => {
    const obj = {
      value: item.values[i],
      frontColor: item.color,
    };

    const label = {
      labelWidth: 40,
      labelComponent: () => <ChartLabel label={xAxisLabels[i]} />,
    };

    const spacing = 2;

    if (j === 0) {
      res.push({...obj, ...label, spacing});
    } else if (j === array.length - 1) {
      res.push({...obj});
    } else {
      res.push({...obj, spacing});
    }
  });
}

export default function Chart() {
  return (
    <View style={{flex: 1}}>
      <BarChart
        disableScroll
        isAnimated
        data={res}
        barWidth={8}
        spacing={16}
        roundedTop
        noOfSections={3}
        xAxisThickness={0}
        yAxisThickness={0}
        dashWidth={20}
        dashGap={12}
      />
    </View>
  );
}

Thanks in advance!

@leineveber
Copy link
Author

Solved.

For anyone, who needs the code:

import React, {useState} from 'react';
import {BarChart, barDataItem} from 'react-native-gifted-charts';
import {View} from 'react-native-ui-lib';
import ChartLabel from './ChartLabel';

const data = [
  {
    values: [5, 40, 77, 81, 43],
    label: 'Hemoglobin',
    color: '#7CDE86',
  },
  {
    values: [40, 5, 50, 23, 79],
    label: 'White blood cell',
    color: '#7CD8DE',
  },
  {
    values: [10, 55, 35, 90, 82],
    label: 'Mean corpuscular volume',
    color: '#7C9DDE',
  },
  {
    values: [22, 45, 50, 60, 30],
    label: 'Hematocrit',
    color: '#A17CDE',
  },
  {
    values: [30, 25, 10, 60, 15],
    label: 'Platelet',
    color: '#DC7CDE',
  },
];

const xAxisLabels = ['01.02', '11.02', '19.02', '12.03', '13.03'];

const getData = (barSpace: number, labelWidth: number, groupWidth: number) => {
  const res: barDataItem[] = [];

  for (let i = 0; i < data.length; i++) {
    data.forEach((item, j, array) => {
      const obj = {
        value: item.values[i],
        frontColor: item.color,
      };

      const label = {
        labelWidth,
        labelComponent: () => (
          <ChartLabel
            label={xAxisLabels[i]}
            labelWidth={labelWidth}
            groupWidth={groupWidth}
          />
        ),
      };

      const spacing = barSpace;

      if (j === 0) {
        res.push({...obj, ...label, spacing});
      } else if (j === array.length - 1) {
        res.push({...obj});
      } else {
        res.push({...obj, spacing});
      }
    });
  }

  return res;
};

export default function Chart() {
  const [width, setWidth] = useState(0);

  const groupSpace = (width * 0.2) / (xAxisLabels.length - 1);
  const groupWidth = (width * 0.8) / xAxisLabels.length;

  const barSpace = (groupWidth * 0.2) / (xAxisLabels.length - 1);
  const barWidth = (groupWidth * 0.8) / xAxisLabels.length;

  const labelWidth = 40;

  return (
    <View
      flex
      onLayout={({
        nativeEvent: {
          layout: {width: calculatedWidth},
        },
      }) => setWidth(calculatedWidth - labelWidth)}>
      <BarChart
        disablePress
        disableScroll
        isAnimated
        data={getData(barSpace, labelWidth, groupWidth)}
        barWidth={barWidth}
        spacing={groupSpace}
        roundedTop
        roundedBottom
        noOfSections={3}
        xAxisThickness={0}
        yAxisThickness={0}
        dashWidth={20}
        dashGap={12}
        initialSpacing={0}
        endSpacing={0}
      />
    </View>
  );
}

IMO, these calculations should be done by the library, so, probably, take it into account

Also, please, take in mind, that I had to use transform: [{translateX: (groupWidth - labelWidth) / 2}] for the label component so it can be in the middle.

And one more thing, when you click on the first bar in the group, opacity applies to label too. Only if you click on the first bar, not others, so it leads one more bug. Had to disable press

@Maximization
Copy link

@leineveber Thanks for posting your solution. It helped me. I saw you're using labelWidth (xAxis) to get the chart width, don't you mean to use yAxisLabelWidth (yAxis) instead?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants