diff --git a/android/src/main/java/com/horcrux/svg/RNSVGRenderableManager.java b/android/src/main/java/com/horcrux/svg/RNSVGRenderableManager.java index 7b7a5701..c2288da4 100644 --- a/android/src/main/java/com/horcrux/svg/RNSVGRenderableManager.java +++ b/android/src/main/java/com/horcrux/svg/RNSVGRenderableManager.java @@ -13,6 +13,7 @@ import android.graphics.Matrix; import android.graphics.Path; import android.graphics.PathMeasure; import android.graphics.RectF; +import android.graphics.Region; import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.ReactApplicationContext; @@ -78,6 +79,24 @@ class RNSVGRenderableManager extends ReactContextBaseJavaModule { isPointInFill(tag, src, successCallback, 0); } + @SuppressWarnings("unused") + @ReactMethod + public void isPointInStroke(int tag, ReadableMap options, Callback successCallback) { + RenderableView svg = RenderableViewManager.getRenderableViewByTag(tag); + if (svg == null) { + successCallback.invoke(false); + return; + } + svg.getPath(null, null); + svg.initBounds(); + Region strokeRegion = svg.mStrokeRegion; + float scale = svg.mScale; + int x = (int) (options.getDouble("x") * scale); + int y = (int) (options.getDouble("y") * scale); + boolean hit = strokeRegion != null && strokeRegion.contains(x, y); + successCallback.invoke(hit); + } + @SuppressWarnings("unused") @ReactMethod public void getTotalLength(int tag, Callback successCallback) { diff --git a/ios/ViewManagers/RNSVGRenderableManager.m b/ios/ViewManagers/RNSVGRenderableManager.m index 44f7be74..92360a54 100644 --- a/ios/ViewManagers/RNSVGRenderableManager.m +++ b/ios/ViewManagers/RNSVGRenderableManager.m @@ -94,6 +94,36 @@ RCT_EXPORT_METHOD(isPointInFill:(nonnull NSNumber *)reactTag options:(NSDictiona attempt:0]; } +RCT_EXPORT_METHOD(isPointInStroke:(nonnull NSNumber *)reactTag options:(NSDictionary *)options callback:(RCTResponseSenderBlock)callback) +{ + if (options == nil) { + RCTLogError(@"Invalid options given to isPointInFill, got: %@", options); + callback(@[[NSNumber numberWithBool:false]]); + return; + } + id xo = [options objectForKey:@"x"]; + id yo = [options objectForKey:@"y"]; + if (![xo isKindOfClass:NSNumber.class] || + ![yo isKindOfClass:NSNumber.class]) { + RCTLogError(@"Invalid x or y given to isPointInFill"); + callback(@[[NSNumber numberWithBool:false]]); + return; + } + [self + withTag:reactTag + success:^(RNSVGRenderable *svg){ + CGFloat x = (CGFloat)[xo floatValue]; + CGFloat y = (CGFloat)[yo floatValue]; + CGPoint point = CGPointMake(x, y); + BOOL hit = CGPathContainsPoint(svg.strokePath, nil, point, NO); + callback(@[[NSNumber numberWithBool:hit]]); + } + fail:^{ + callback(@[[NSNumber numberWithBool:false]]); + } + attempt:0]; +} + RCT_EXPORT_METHOD(getTotalLength:(nonnull NSNumber *)reactTag callback:(RCTResponseSenderBlock)callback) { [self diff --git a/src/elements/Shape.tsx b/src/elements/Shape.tsx index 85452894..bb61740a 100644 --- a/src/elements/Shape.tsx +++ b/src/elements/Shape.tsx @@ -99,7 +99,7 @@ export default class Shape
extends Component
{ return; } const handle = findNodeHandle(this.root as Component); - RNSVGRenderableManager.isPointInStroke(handle, options, callback); // TODO + RNSVGRenderableManager.isPointInStroke(handle, options, callback); }; getTotalLength = (callback: () => void) => { if (!callback) { diff --git a/src/elements/Svg.tsx b/src/elements/Svg.tsx index b4181cc2..64ca1010 100644 --- a/src/elements/Svg.tsx +++ b/src/elements/Svg.tsx @@ -88,7 +88,7 @@ export default class Svg extends Shape< this.root && this.root.setNativeProps(props); }; - toDataURL = (callback: () => void, options: Object) => { + toDataURL = (callback: () => void, options?: Object) => { if (!callback) { return; }