Search code examples
javascriptreactjsreact-nativereact-native-svg

How to draw a circle with n slices


I am using react-native-svg module and I want to draw a circle divided to n slices. My circle radius is 41 and the center of it is (50, 50) for example for n=6 I want to draw something like this:

circle with 5 slics


Solution

  • I've worked hard to find a solution for you

    But I learned a lot of things along the way

    Based on this article

    import Svg, {Path} from 'react-native-svg';
    
    import React from 'react';
    import {View, StyleSheet} from 'react-native';
    
    export default class SvgExample extends React.Component {
      slice() {
        let slices = [];
    
      //option 1  Equal size pieces
        slices.push({percent: 0.25, color: 'blue'});
        slices.push({percent: 0.10, color: 'red'});
        slices.push({percent: 0.28, color: 'green'});
        slices.push({percent: 0.19, color: 'yellow'});
    
    
        //option 2  Different size pieces
        // const numberOfSlice = 6; //number for slice
    
        // const colorArr = ['red', 'green', 'yellow', 'blue']; //color the slice
        // for (let i = 0; i < numberOfSlice; i++) {
        //   slices.push({percent: 1 / numberOfSlice, color: colorArr[i] || 'gray'});
        // }
    
        let cumulativePercent = 0;
    
        function getCoordinatesForPercent(percent) {
          const x = Math.cos(2 * Math.PI * percent);
          const y = Math.sin(2 * Math.PI * percent);
          return [x, y];
        }
    
        let arr = [];
        arr = slices.map(slice => {
          const [startX, startY] = getCoordinatesForPercent(cumulativePercent);
          cumulativePercent += slice.percent;
          const [endX, endY] = getCoordinatesForPercent(cumulativePercent);
          const largeArcFlag = slice.percent > 0.5 ? 1 : 0;
          const pathData = [
            `M ${startX} ${startY}`, // Move
            `A 1 1 0 ${largeArcFlag} 1 ${endX} ${endY}`, // Arc
            'L 0 0', // Line
          ].join(' ');
          return <Path d={pathData} fill={slice.color} key={pathData} />;
        });
        return arr;
      }
    
      render() {
        return (
          <View
            style={[
              StyleSheet.absoluteFill,
              {alignItems: 'center', justifyContent: 'center'},
            ]}>
            <Svg
              height="100"
              width="100"
              viewBox="-1 -1 2 2"
              style={{transform: [{rotate: '-90deg'}]}}>
              {this.slice()}
            </Svg>
          </View>
        );
      }
    }
    
    

    expo codesandbox

    option 1 option 2