简体   繁体   English

react-native [Expo]:我可以提高 PanResponder 的输入采样率吗?

[英]react-native [Expo]: can I increase PanResponder's input sampling rate?

I am currently implementing a react-native-svg based drawing input for my Expo application (it is a slight modification of this answer: link ).我目前正在为我的 Expo 应用程序实现一个基于react-native-svg的绘图输入(这是对这个答案的轻微修改: 链接)。 I use a PanResponder to register move events and create different paths that I then display as multiple Polyline elements while the user draws on the view like so:我使用PanResponder来注册移动事件并创建不同的路径,然后当用户在视图上绘制时,这些路径显示为多个Polyline元素,如下所示:

const GesturePath: React.FC<GesturePathProps> = ({
  paths,
  color,
  width,
  height,
  strokeWidth,
}) => {
  return (
    <Svg height='100%' width='100%' viewBox={`0 0 ${width} ${height}`}>
      {paths.map((path) => (
        <Polyline
          key={path.id}
          points={path.points.map((p) => `${p.x},${p.y}`).join(" ")}
          fill='none'
          stroke={color}
          strokeWidth={strokeWidth}
        />
      ))}
    </Svg>
  );
};

Unfortunately, the lines I produce are extremely rough and jagged and I believe the PanResponder.onPanResponderMove handler is fired too infrequently for my needs (on average it is called every 50ms on the Android Pixel 4 emulator and I'm not sure if I can expect more from a real device).不幸的是,我制作的线条非常粗糙且参差不齐,我相信PanResponder.onPanResponderMove处理程序的触发频率太低,无法满足我的需要(在 Android Pixel 4 模拟器上平均每 50 毫秒调用一次,我不确定我是否可以期待更多来自真实设备)。

Maybe there is better candidate than PanResponder for handling gestures in my use case?在我的用例中,也许有比 PanResponder 更好的人选来处理手势?

I have implemented a smoothing function (based on this answer link ) that behaves correctly but since the points are so distant from each other the user's input gets noticeably distorted.我已经实现了一个平滑的 function (基于此答案链接),它的行为正确,但由于这些点彼此相距太远,用户的输入会明显失真。

Here's an example without smoothing:这是一个没有平滑的例子:

SVG 绘图示例

Below my GestureHandler implementation:在我的 GestureHandler 实现下面:

const GestureRecorder: React.FC<GestureRecorderProps> = ({ addPath }) => {
  const buffRef = useRef<Position[]>([]);
  const pathRef = useRef<Position[]>([]);
  const timeRef = useRef<number>(Date.now());
  const pathIdRef = useRef<number>(0);

  const panResponder = useRef(
    PanResponder.create({
      onStartShouldSetPanResponder: () => true,
      onStartShouldSetPanResponderCapture: () => true,
      onMoveShouldSetPanResponder: () => true,
      onMoveShouldSetPanResponderCapture: () => true,

      onPanResponderMove: (event) => {
        // workaround for release event
        // not working consistently on android
        if (Date.now() - timeRef.current > RELEASE_TIME) {
          pathIdRef.current += 1;
          pathRef.current = [];
          buffRef.current = [];
        }
        timeRef.current = Date.now();

        pathRef.current.push({
          x: event.nativeEvent.locationX,
          y: event.nativeEvent.locationY,
        });

        addPath({
          points: calculateSmoothedPath(event),
          id: pathIdRef.current,
        });
      },

      // not working on Android
      // release event is not consistent
      // onPanResponderRelease: () => {
      // pathIdRef.current += 1;
      // pathRef.current = [];
      // buffRef.current = [];
      // },
    })
  ).current;

  const calculateSmoothedPath = (event: GestureResponderEvent) => { 
    // implementation
    // ...
    // see: https://stackoverflow.com/questions/40324313/svg-smooth-freehand-drawing
  }

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

Side Note边注

I have not found any documentation on PanResponder suggesting that a sample rate configuration option exists so I am totally open to alternatives (even dropping the PanResponder + native SVG method entirely) as long as I don't have to eject the expo project and I can have control over the layout (I don't want to use external components that come with specific UIs).我没有在 PanResponder 上找到任何文档表明存在采样率配置选项,因此我完全愿意接受替代方案(甚至完全放弃 PanResponder + 本机 SVG 方法),只要我不必弹出 expo 项目并且我可以可以控制布局(我不想使用特定 UI 附带的外部组件)。

I have tried using the expo-pixi library (specifically the Sketch component), but the repository seems not to be mantained anymore and the expo client crashes consistently when using it.我曾尝试使用expo-pixi库(特别是Sketch组件),但存储库似乎不再被维护,并且 expo 客户端在使用它时始终崩溃。

I have been trying different solutions after I posted the question and I have ended up changing my GestureHandler implementation slightly.发布问题后,我一直在尝试不同的解决方案,最终我稍微改变了我的GestureHandler实现。 I am now using PanGestureHandler from react-native-gesture-handler instead of PanResponder .我现在使用来自react-native-gesture-handlerPanGestureHandler而不是PanResponder This component lets the user specify a minDist prop for tweaking activation, here is the description from the docs:这个组件允许用户指定一个minDist来调整激活,这里是来自文档的描述:

Minimum distance the finger (or multiple finger) need to travel before the handler activates.在处理程序激活之前手指(或多根手指)需要移动的最小距离。 Expressed in points.以点数表示。

Below the new implementation:在新的实现下面:

<PanGestureHandler
  minDist={1}
  onGestureEvent={(e) => {
    // same code from the previous onPanResponderMove
  }
>
  <View style={StyleSheet.absoluteFill} collapsable={false} />
</PanGestureHandler>

I had also overestimated my GPU capabilities while running the emulator, after building an APK and testing on a real device I realized the drawing input behaves much more fluidly.在运行模拟器时,我还高估了我的 GPU 功能,在构建 APK 并在真实设备上进行测试后,我意识到绘图输入的行为更加流畅。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM