4

I am currently using this module: https://github.com/mxmzb/react-native-gesture-detector. I want to be able to draw a line from the points created. however, it only seems to output circles.

It has a "Create Gesture" view:

<View style={{ position: "relative", width: "100%", height: "100%" }}>
    <GesturePath
        path={gesture.map(coordinate => {
            if (recorderOffset) {
                return {
                    x: coordinate.x + recorderOffset.x,
                    y: coordinate.y + recorderOffset.y,
                };
            }

            return coordinate;
        })}
        color="green"
        slopRadius={30}
        center={false}
    />
</View>

GesturePath is defined like so:

const GesturePath = ({ path, color, slopRadius, center = true }: GesturePathProps) => {
  const baseStyle: ViewStyle = {
    position: "absolute",
    top: center ? "50%" : 0,
    left: center ? "50%" : 0,
    opacity: 1,
  };

  return (
    <>
      {path.map((point, index) => (
        <Animated.View
          style={Object.assign({}, baseStyle, {
            width: slopRadius,
            height: slopRadius,
            borderRadius: slopRadius,
            backgroundColor: color,
            marginLeft: point.x - slopRadius,
            marginTop: point.y - slopRadius,
          })}
          key={index}
        />
      ))}
    </>
  );
};

When you draw on that view, it outlines the path using dots, like so:

enter image description here

I would like it to be a smooth line and not a series of circles that the above image.

JamesG
  • 1,552
  • 8
  • 39
  • 86
  • Have you tried this one: https://github.com/react-native-community/react-native-svg – Shehan Dhaleesha May 09 '20 at 05:04
  • @ShehanDhaleesha I had a quick look at that but it seemed impossible to draw a squiggly line and get coordinates. – JamesG May 09 '20 at 13:27
  • Am I right assuming you already have the points and you __only__ want to draw a smooth line from those points ? – grodzi May 10 '20 at 10:49
  • @grodzi - I have the component linked above that has all the functionality I want except it only adds dots to the coordinates it makes. I would like it to be connected by a line and if that line is squiqqly, I would like it to be smooth. – JamesG May 10 '20 at 12:17
  • @jamesG what happens if you use slopRadius={1} ? – uokesita May 10 '20 at 12:43
  • @uokesita I get a 1px circle on the coordinate instead of a larger 30px one. – JamesG May 10 '20 at 13:07

1 Answers1

10

You are going to need something like a Canvas to draw lines instead of pixels (with Views). React Native does not currently come with a Canvas implementation.

The easiest way to do this in expo is to use the react-native-svg library.

Using that, you can draw a polyline from your gesture data with the following implementation:

import Svg, { Polyline } from 'react-native-svg';

const GesturePath = ({ path, color }) => {
  const { width, height } = Dimensions.get('window');
  const points = path.map(p => `${p.x},${p.y}`).join(' ');
  return (
    <Svg height="100%" width="100%" viewBox={`0 0 ${width} ${height}`}>
        <Polyline
          points={points}
          fill="none"
          stroke={color}
          strokeWidth="1"
        />
    </Svg>    
  );
};

You can also record gestures without the react-native-gesture-detector library by using the in-built React Native PanResponder. Here is an example:

const GestureRecorder = ({ onPathChanged }) => {
  const pathRef = useRef([]);

  const panResponder = useRef(
    PanResponder.create({
      onMoveShouldSetPanResponder: () => true,
      onPanResponderGrant: () => {
        pathRef.current = [];
      },
      onPanResponderMove: (event) => {
        pathRef.current.push({
          x: event.nativeEvent.locationX,
          y: event.nativeEvent.locationY,
        });
        // Update path real-time (A new array must be created
        // so setState recognises the change and re-renders the App):
        onPathChanged([...pathRef.current]);
      },
      onPanResponderRelease: () => {
        onPathChanged(pathRef.current);
      }
    })
  ).current;

  return (
    <View
      style={StyleSheet.absoluteFill}
      {...panResponder.panHandlers}
    />
  );
}

See this snack for a working App tying everything together: https://snack.expo.io/@mtkopone/draw-gesture-path

mtkopone
  • 5,955
  • 2
  • 27
  • 30
  • I'm confused, I cannot see how this draws a line dependent on the users touch. ? – JamesG May 13 '20 at 04:14
  • I understook from your question that you can already record them with the `react-native-gesture-detector`-library. Once recorded by that component, you can use svg to draw them. However, for this case `react-native-gesture-detector` is not totally necessary, as the default PanResponder from React Native will do the same job. I will update the answer to include recording touches. – mtkopone May 13 '20 at 04:59
  • You update is so close to what I am wanting, but I feel as though I explained it wrong. Your solution doesn't show the line as I am drawing "real time" which is the effect I am looking for. I am sorry, I am a Junior developer and very new to this so please forgive my bombardment of questions. – JamesG May 13 '20 at 06:04
  • No worries. I was kinda expecting that :) Updated the answer and the snack, it's just 1 line more. – mtkopone May 13 '20 at 06:26
  • Hey @mtkopone - That is fantastic, Thank you so much for all the effort you have put in. I really really appreciate this. Than you. – JamesG May 13 '20 at 07:21