Search code examples
react-nativeautolayoutstylesshapes

React-Native : How to draw shapes with random number of sides ( number of sides will be a user input value)?


If a user input number 4, generated shape will become a square. If user input 9 the shape will become a nonagon. This should be a react-native solution :) Any ideas?


Solution

  • Code should be self-explanatory. You locate the points on a circle, and connect them with lines with the help of svg polygon.

    Snack

    import React, { useState, useEffect } from 'react';
    import { View, StyleSheet, Dimensions, Text, TextInput } from 'react-native';
    import Svg, { Polygon } from 'react-native-svg';
    import Constants from 'expo-constants';
    
    export default function App() {
      const windowWidth = Dimensions.get('window').width;
      const Center = windowWidth / 2;
      const Radius = Center - 20;
    
      const [numSides, setNumSides] = useState(3);
      const [polygonPoints, setPolygonPoints] = useState();
    
      useEffect(() => {
        let newPolyPoints = '';
        const angle = 2 * Math.PI / numSides;
        for (let side = 0; side < numSides; side++) {
          const x = Math.cos(angle * side) * Radius + Center;
          const y = Math.sin(angle * side) * Radius + Center;
          newPolyPoints = `${newPolyPoints} ${x},${y}`;
        }
        setPolygonPoints(newPolyPoints);
      }, [numSides]);
    
      const inputIsValid = t => {
        const int = parseInt(t, 10);
        return isNaN(int) === false && int >= 3;
      }
    
      return (
        <View style={styles.container}>
          <View style={styles.inputContainer}>
            <Text style={styles.label}>
              {'Number of sides: '}
            </Text>
            <TextInput
              style={styles.textInput}
              defaultValue={numSides.toString()}
              selectTextOnFocus
              onChangeText={t => {
                if (inputIsValid(t)) {
                  const int = parseInt(t, 10);
                  setNumSides(int);
                }
              }}
            />
          </View>
          <Svg style={styles.svg} width={windowWidth} height={windowWidth}>
            <Polygon
              points={polygonPoints}
              fill="lime"
              stroke="purple"
              strokeWidth="1"
            />
          </Svg>
        </View>
      );
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        paddingTop: Constants.statusBarHeight,
        backgroundColor: '#ecf0f1',
        padding: 8,
      },
      inputContainer: {
        flexDirection: 'row',
        alignItems: 'center',
        marginVertical: 20,
        marginHorizontal: 12,
      },
      label: {
        fontSize: 18,
      },
      textInput: {
        backgroundColor: 'white',
        flex: 1,
        fontSize: 18,
      },
      svg: {
        aspectRatio: 1,
        backgroundColor: 'tomato',
      },
    });