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.
Image to indicate in which areas I am interested in having coordinates.
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,
}
})