reactjs - react-native [Expo]:我可以增加 PanResponder 的输入采样率吗?
问题描述
我目前正在为我的 Expo 应用程序实现一个基于react-native-svg的绘图输入(这是对这个答案的轻微修改:链接)。我使用 aPanResponder
来注册移动事件并创建不同的路径,然后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 更好的人选来处理手势?
我已经实现了一个平滑功能(基于此答案链接),它的行为正确,但由于这些点彼此相距太远,用户的输入会明显失真。
这是一个没有平滑的例子:
在我的 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
稍微改变了我的实现。我现在使用PanGestureHandler
from react-native-gesture-handler而不是PanResponder
. 该组件允许用户指定minDist
用于调整激活的道具,以下是文档中的描述:
在处理程序激活之前手指(或多根手指)需要移动的最小距离。以点数表示。
在新的实现下面:
<PanGestureHandler
minDist={1}
onGestureEvent={(e) => {
// same code from the previous onPanResponderMove
}
>
<View style={StyleSheet.absoluteFill} collapsable={false} />
</PanGestureHandler>
在运行模拟器时,我还高估了我的 GPU 功能,在构建了一个 APK 并在真实设备上进行测试后,我意识到绘图输入的行为更加流畅。
推荐阅读
- php - centos httpd php版本与php版本命令行不同
- android - 是否有任何 Android API 来检测图像中的人脸?
- sql - 多行返回oracle
- plugins - Html Table Export插件不起作用不显示视图表数据导出
- python - 如何在没有循环的熊猫系列中通过索引搜索数据
- python - 在 Python 的大型数组中寻找“打印”位置?
- excel - VBA - 设置 Excel 工作簿默认另存为名称
- python - Python 3中的双行循环搜索?
- r - 使用 dplyr 以根据另一个 df 更改列值
- slack-api - Slack API chat.postMessage URL 展开