1

Task at hand:

enter image description here

What I've taken a lot at so far:

  1. Pie chart from [https://github.com/JesperLekland/react-native-svg-charts-examples][2]

Here I divided the entire pie into 50 units of 1 value, inorder to get the Split-bar effect. I can pass the color according to the image shown above. But how can I add the inner lines(red and green) and the data inside? Any help would be appreciated!

Blake
  • 157
  • 4
  • 13

1 Answers1

2

So the approach I would take is to make the outer ring a PieChart (like you have done), but to make the inner circle a ProgressCircle (https://github.com/JesperLekland/react-native-svg-charts#progresscircle) as this component naturally looks like the inner circle in the picture. You can change its backgroundColor prop to red and its progressColor prop to green.

import {PieChart, ProgressCircle} from 'react-native-svg-charts';
import Svg, {Text as SvgText, ForeignObject} from 'react-native-svg';
import Icon from 'react-native-vector-icons/FontAwesome5';

// ...

class CustomPieChart extends React.PureComponent {
  render() {
    const data = Array.apply(null, Array(50)).map(Number.prototype.valueOf, 1);

    // Change to whatever your fill function looks like...
    const getFill = (index) => {
      if (index > 30) return 'purple';
      if (index > 20) return 'blue';
      if (index > 10) return 'green';
      return 'red';
    };

    const pieData = data.map((value, index) => ({
      value,
      svg: {
        fill: getFill(index),
      },
      key: `pie-${index}`,
    }));

    return (
      <PieChart innerRadius="90%" style={styles.pieChart} data={pieData}>
        <ProgressCircle
          style={styles.progressCircle}
          progress={0.7}
          backgroundColor="red"
          progressColor="green">
          <ForeignObject x={-100} y={-100}>
            <View style={styles.progressCircleContentContainer}>
              <Text style={{...styles.text, color: 'green', marginBottom: 5}}>
                Active
              </Text>
              <View
                style={{
                  ...styles.progressCircleContentView,
                  width: 110,
                }}>
                <Icon name="heartbeat" size={30} color="red" />
                <Text style={styles.text}>72 BPM</Text>
              </View>
              <View style={styles.progressCircleContentView}>
                <Icon name="shoe-prints" size={30} color="red" />
                <Text style={styles.text}>4,565</Text>
                <Icon name="bolt" size={30} color="red" />
                <Text style={styles.text}>45 min</Text>
              </View>
              <View style={styles.progressCircleContentView}>
                <Icon name="fire-alt" size={30} color="red" />
                <Text style={styles.text}>1,856</Text>
                <Icon name="glass-whiskey" size={30} color="red" />
                <Text style={styles.text}>Active</Text>
              </View>
              <View style={{...styles.progressCircleContentView, width: 150}}>
                <Icon name="moon" size={30} color="red" />
                <Text style={styles.text}>6 hr 10 min</Text>
              </View>
            </View>
          </ForeignObject>
        </ProgressCircle>
      </PieChart>
    );
  }
}

const styles = StyleSheet.create({
  pieChart: {
    height: 300,
  },
  progressCircle: {
    height: 250,
    marginTop: 25,
  },
  progressCircleContentContainer: {
    alignItems: 'center',
    width: 200,
    height: 200,
    transform: [],
  },
  progressCircleContentView: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    width: 200,
    marginBottom: 5,
  },
  text: {
    fontSize: 20,
  },
});

What this exmample doesn't do:

  • Add the backdrop shadow on the circle
  • Add the icons on the outside of the outer circle

The custom shapes were made with react-native-svg, the library that is used by react-native-svg-charts internally. You can read its documentation here: https://github.com/react-native-community/react-native-svg.


How it looks:

showcase

5eb
  • 14,798
  • 5
  • 21
  • 65
  • Thank you so so much! I will try this out now and let you know! – Blake Sep 04 '20 at 20:59
  • For some reason, the progress bar and the icons are not loading. There are no errors however - https://snack.expo.io/HnAtix!VG Please take a look? Here is my project^ – Blake Sep 04 '20 at 21:24
  • I've used this import statement for Ionicons: `import Icon from 'react-native-vector-icons/Ionicons'`. But the biggest thing is you need to remove the comment I left in my example: `// Add further ForeignObject for other text and icons...` – 5eb Sep 04 '20 at 21:53
  • Also be sure to select android or ios if you're running it in the snack, it's not going to display correctly with web. If you see the question mark that is because react native vector icons requires some configuration that you can't do in a snack (as far as I know). So you'll probably want to configure it locally and test it on a device. For the instructions you can refer to this: https://github.com/oblador/react-native-vector-icons#installation. – 5eb Sep 04 '20 at 22:01
  • Here's my adjusted fork of your snack https://snack.expo.io/@bvdl/chart-draft. – 5eb Sep 04 '20 at 22:06
  • Hey is there a way to split each foreign object into Views and stack them on each other rather than hard-coding the coordinates? – Blake Sep 09 '20 at 00:36
  • Yes it is possible, I've edited my answer to show how. The `ForeignObject` needs coordinates, but what's inside it doesn't necessarily. You're right that all those coordinates looked pretty ugly, I think this layout is a lot cleaner. Btw I've changed the icon set from `IonIcons` to `FontAwesome5` as it looks more like your picture – 5eb Sep 09 '20 at 10:39