1

I am creating an android/ios app. One of the features that I want to implement are drawing within the given shape (letter). Currently I got a component that puts random English alphabet capital letter on the screen and allows user to draw with finger drag. However, I am struggling for few months already with validation of such drawing mechanism. User cannot draw outside of the shape and has to have draw whole letter with finger. I would be able to do it for single letter with hardcoded values, however I am going for generic approach thus I need to get shape of the letter in coordinates, whether all borders or all actual pixel coordinates.

I am able to track the points where user already drawn as I use that input to create path which is then translated into the line on the screen. I would like to know how can I get coordinates array of the letter that is created with <Text> tag from react-native-svg library?

This is what I would expect user to do as correct result. Correct user behaviour

Image to indicate in which areas I am interested in having coordinates. Coordinates that I am interested in.

Whole react-native component that can be tested with @luncheon/simplify-svg-path and react-native-svg package.

import React, { Component } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import colorStyles from '../../styles/colorStyles'
import Svg, {
    Text as SvgText,
    Path,
} from 'react-native-svg';
import simplifySvgPath from '@luncheon/simplify-svg-path';

export default class OutlineShape extends Component {
    constructor(props) {
        super(props)
        this.state = {
            currentPath: null,
            points: []
        }
    }

    createSVGPath(points) {
        if (points.length > 1) {
            try {
                return simplifySvgPath(points, {
                    precision: 5,
                    tolerance: 1,
                });
            } catch (error) {
                console.log(error);
            }
        } else if (points.length === 1) {
            return `M${points[0][0]},${points[0][1]} L${points[0][0]},${points[0][1]}`;
        }
        return '';
    }
    // TODO: You can see what you drawn from this.state.points. I need to figure out the shape/borders of the char (B) and track what was drawn.
    // Like if there is no points between two borders in the middle of the letter then we are sure its bad already.
    render() {
        return (
            <View style={styles.container} >
                <Svg style={styles.contentContainer} height='100%' width='100%' fill="#000000" >
                    <SvgText fill="#FFFFFF" x="50%" y="75%" textAnchor="middle" fontSize="512"
                        onMoveShouldSetResponder={() => true}
                        onStartShouldSetResponder={() => true}
                        onMoveShouldSetPanResponder={() => true}
                        onResponderMove={(e) => {
                            console.log(e.nativeEvent)
                            this.state.points.push([e.nativeEvent.locationX, e.nativeEvent.locationY]);
                            this.setState({ currentPath: this.createSVGPath(this.state.points, 1, true) });
                        }}
                        onResponderRelease={() => {
                            this.setState({ points: [], currentPath: null })
                            // TODO: Validate that whole path was within letter and whole letter is completed.
                        }}
                        onLayout={(e) => {
                            console.log(e.currentTarget)
                        }}
                    >B</SvgText>
                    <Path
                        d={this.state.currentPath}
                        fill="none"
                        stroke={colorStyles.intenseColor}
                        strokeWidth={5}
                        opacity={1}
                    />
                </Svg>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: colorStyles.lowIntenseColor,
        flexDirection: 'column',
    },
    contentContainer: {
        position: "absolute",
        top: 0, left: 0,
        right: 0, bottom: 0,
    }
})
Karolis Kajenas
  • 1,523
  • 1
  • 15
  • 23

0 Answers0