From de8a7632f6ad4e74c93e94e17049406c4d807bc7 Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Wed, 15 Jan 2025 11:49:55 +0100 Subject: [PATCH] fix: properly handle touch events outside the Svg (#2611) # Summary Fixes #2585 Improve the `onPress` events by ignoring touches outside the `Svg` view. This is implemented as follows: * on Android by clipping the Android's element dimensions to (0, 0, canvas width, canvas height) * on Apple by improving `hitTest` to exclude touches outside the bounds of (0, 0, bounds width, bounds height) https://github.com/user-attachments/assets/59417493-d849-47df-84e8-d5b0a6045b00 --- .../src/main/java/com/horcrux/svg/VirtualView.java | 12 ++++++++---- apple/Elements/RNSVGSvgView.mm | 3 +++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/android/src/main/java/com/horcrux/svg/VirtualView.java b/android/src/main/java/com/horcrux/svg/VirtualView.java index d5160101..815b236d 100644 --- a/android/src/main/java/com/horcrux/svg/VirtualView.java +++ b/android/src/main/java/com/horcrux/svg/VirtualView.java @@ -591,10 +591,14 @@ public abstract class VirtualView extends ReactViewGroup { int bottom = (int) Math.ceil(mClientRect.bottom); setMeasuredDimension(width, height); if (!(this instanceof GroupView)) { - setLeft(left); - setTop(top); - setRight(right); - setBottom(bottom); + SvgView root = this.getSvgView(); + // Prevent going out of the root view bounds to properly handle touch events + if (root != null) { + setLeft(Math.max(left, 0)); + setTop(Math.max(top, 0)); + setRight(Math.min(right, root.getWidth())); + setBottom(Math.min(bottom, root.getHeight())); + } } EventDispatcher eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(mContext, getId()); diff --git a/apple/Elements/RNSVGSvgView.mm b/apple/Elements/RNSVGSvgView.mm index 7cb97e4d..a00e1433 100644 --- a/apple/Elements/RNSVGSvgView.mm +++ b/apple/Elements/RNSVGSvgView.mm @@ -342,6 +342,9 @@ using namespace facebook::react; - (RNSVGPlatformView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { + if (point.x < 0 || point.y < 0 || point.x > self.bounds.size.width || point.y > self.bounds.size.height) { + return nil; + } CGPoint transformed = point; if (self.align) { transformed = CGPointApplyAffineTransform(transformed, _invViewBoxTransform);