簡體   English   中英

react-native [Expo]:我可以提高 PanResponder 的輸入采樣率嗎?

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

我目前正在為我的 Expo 應用程序實現一個基於react-native-svg的繪圖輸入(這是對這個答案的輕微修改: 鏈接)。 我使用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>
  );
};

不幸的是,我制作的線條非常粗糙且參差不齊,我相信PanResponder.onPanResponderMove處理程序的觸發頻率太低,無法滿足我的需要(在 Android Pixel 4 模擬器上平均每 50 毫秒調用一次,我不確定我是否可以期待更多來自真實設備)。

在我的用例中,也許有比 PanResponder 更好的人選來處理手勢?

我已經實現了一個平滑的 function (基於此答案鏈接),它的行為正確,但由於這些點彼此相距太遠,用戶的輸入會明顯失真。

這是一個沒有平滑的例子:

SVG 繪圖示例

在我的 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}
    />
  );
};

邊注

我沒有在 PanResponder 上找到任何文檔表明存在采樣率配置選項,因此我完全願意接受替代方案(甚至完全放棄 PanResponder + 本機 SVG 方法),只要我不必彈出 expo 項目並且我可以可以控制布局(我不想使用特定 UI 附帶的外部組件)。

我曾嘗試使用expo-pixi庫(特別是Sketch組件),但存儲庫似乎不再被維護,並且 expo 客戶端在使用它時始終崩潰。

發布問題后,我一直在嘗試不同的解決方案,最終我稍微改變了我的GestureHandler實現。 我現在使用來自react-native-gesture-handlerPanGestureHandler而不是PanResponder 這個組件允許用戶指定一個minDist來調整激活,這里是來自文檔的描述:

在處理程序激活之前手指(或多根手指)需要移動的最小距離。 以點數表示。

在新的實現下面:

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

在運行模擬器時,我還高估了我的 GPU 功能,在構建 APK 並在真實設備上進行測試后,我意識到繪圖輸入的行為更加流暢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM