diff --git a/android/src/main/java/com/horcrux/svg/UseShadowNode.java b/android/src/main/java/com/horcrux/svg/UseShadowNode.java index 909529a1..1c5592ec 100644 --- a/android/src/main/java/com/horcrux/svg/UseShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/UseShadowNode.java @@ -73,6 +73,24 @@ class UseShadowNode extends RenderableShadowNode { } } + @Override + public int hitTest(float[] src) { + if (!mInvertible) { + return -1; + } + + float[] dst = new float[2]; + mInvMatrix.mapPoints(dst, src); + + VirtualNode template = getSvgShadowNode().getDefinedTemplate(mHref); + int hitChild = template.hitTest(dst); + if (hitChild != -1) { + return (template.isResponsible() || hitChild != template.getReactTag()) ? hitChild : getReactTag(); + } + + return -1; + } + @Override protected Path getPath(Canvas canvas, Paint paint) { // todo: diff --git a/ios/Elements/RNSVGGroup.m b/ios/Elements/RNSVGGroup.m index 14138de2..85bd1dd6 100644 --- a/ios/Elements/RNSVGGroup.m +++ b/ios/Elements/RNSVGGroup.m @@ -61,6 +61,7 @@ return YES; }]; + [self setHitArea:[self getPath:context]]; [self popGlyphContext]; } @@ -113,16 +114,19 @@ - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix); - - UIView *hitSelf = [super hitTest:transformed withEvent:event]; - if (hitSelf) { - return hitSelf; - } - + CGPathRef clip = [self getClipPath]; if (clip && !CGPathContainsPoint(clip, nil, transformed, self.clipRule == kRNSVGCGFCRuleEvenodd)) { return nil; } + + if (!event) { + NSPredicate *const anyActive = [NSPredicate predicateWithFormat:@"active == TRUE"]; + NSArray *const filtered = [self.subviews filteredArrayUsingPredicate:anyActive]; + if ([filtered count] != 0) { + return filtered.firstObject; + } + } for (RNSVGNode *node in [self.subviews reverseObjectEnumerator]) { if (![node isKindOfClass:[RNSVGNode class]]) { @@ -142,7 +146,12 @@ return (node.responsible || (node != hitChild)) ? hitChild : self; } } - + + UIView *hitSelf = [super hitTest:transformed withEvent:event]; + if (hitSelf) { + return hitSelf; + } + return nil; } diff --git a/ios/Elements/RNSVGUse.m b/ios/Elements/RNSVGUse.m index ab2f4af7..cd9dcf87 100644 --- a/ios/Elements/RNSVGUse.m +++ b/ios/Elements/RNSVGUse.m @@ -51,5 +51,21 @@ } } +- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { + const CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix); + RNSVGNode const* template = [self.svgView getDefinedTemplate:self.href]; + if (event) { + self.active = NO; + } else if (self.active) { + return self; + } + UIView const* hitChild = [template hitTest:transformed withEvent:event]; + if (hitChild) { + self.active = YES; + return self; + } + return nil; +} + @end diff --git a/ios/RNSVGRenderable.m b/ios/RNSVGRenderable.m index 74414460..b6821200 100644 --- a/ios/RNSVGRenderable.m +++ b/ios/RNSVGRenderable.m @@ -264,21 +264,19 @@ { CGPathRelease(_hitArea); _hitArea = nil; - if (self.responsible) { - // Add path to hitArea - CGMutablePathRef hitArea = CGPathCreateMutableCopy(path); - - if (self.stroke && self.strokeWidth) { - // Add stroke to hitArea - CGFloat width = [self relativeOnOther:self.strokeWidth]; - CGPathRef strokePath = CGPathCreateCopyByStrokingPath(hitArea, nil, width, self.strokeLinecap, self.strokeLinejoin, self.strokeMiterlimit); - CGPathAddPath(hitArea, nil, strokePath); - CGPathRelease(strokePath); - } - - _hitArea = CGPathRetain(CFAutorelease(CGPathCreateCopy(hitArea))); - CGPathRelease(hitArea); + // Add path to hitArea + CGMutablePathRef hitArea = CGPathCreateMutableCopy(path); + + if (self.stroke && self.strokeWidth) { + // Add stroke to hitArea + CGFloat width = [self relativeOnOther:self.strokeWidth]; + CGPathRef strokePath = CGPathCreateCopyByStrokingPath(hitArea, nil, width, self.strokeLinecap, self.strokeLinejoin, self.strokeMiterlimit); + CGPathAddPath(hitArea, nil, strokePath); + CGPathRelease(strokePath); } + + _hitArea = CGPathRetain(CFAutorelease(CGPathCreateCopy(hitArea))); + CGPathRelease(hitArea); }