mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-06-05 07:59:28 +00:00
Fix hit testing when using react-native transform arrays.
This commit is contained in:
@@ -191,12 +191,13 @@ class GroupView extends RenderableView {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
int hitTest(final float[] src) {
|
int hitTest(final float[] src) {
|
||||||
if (!mInvertible) {
|
if (!mInvertible || !mTransformInvertible) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
float[] dst = new float[2];
|
float[] dst = new float[2];
|
||||||
mInvMatrix.mapPoints(dst, src);
|
mInvMatrix.mapPoints(dst, src);
|
||||||
|
mInvTransform.mapPoints(dst, src);
|
||||||
|
|
||||||
int x = Math.round(dst[0]);
|
int x = Math.round(dst[0]);
|
||||||
int y = Math.round(dst[1]);
|
int y = Math.round(dst[1]);
|
||||||
|
|||||||
@@ -428,12 +428,13 @@ abstract public class RenderableView extends VirtualView {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
int hitTest(final float[] src) {
|
int hitTest(final float[] src) {
|
||||||
if (mPath == null || !mInvertible) {
|
if (mPath == null || !mInvertible || !mTransformInvertible) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
float[] dst = new float[2];
|
float[] dst = new float[2];
|
||||||
mInvMatrix.mapPoints(dst, src);
|
mInvMatrix.mapPoints(dst, src);
|
||||||
|
mInvTransform.mapPoints(dst, src);
|
||||||
int x = Math.round(dst[0]);
|
int x = Math.round(dst[0]);
|
||||||
int y = Math.round(dst[1]);
|
int y = Math.round(dst[1]);
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
package com.horcrux.svg;
|
package com.horcrux.svg;
|
||||||
|
|
||||||
|
import android.graphics.Matrix;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.facebook.infer.annotation.Assertions;
|
import com.facebook.infer.annotation.Assertions;
|
||||||
@@ -990,8 +991,10 @@ class RenderableViewManager extends ViewGroupManager<VirtualView> {
|
|||||||
resetTransformProperty(node);
|
resetTransformProperty(node);
|
||||||
} else {
|
} else {
|
||||||
setTransformProperty(node, matrix);
|
setTransformProperty(node, matrix);
|
||||||
node.mTransform = node.getMatrix();
|
|
||||||
}
|
}
|
||||||
|
Matrix m = node.getMatrix();
|
||||||
|
node.mTransform = m;
|
||||||
|
node.mTransformInvertible = m.invert(node.mInvTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactProp(name = "propList")
|
@ReactProp(name = "propList")
|
||||||
|
|||||||
@@ -971,12 +971,13 @@ class TSpanView extends TextView {
|
|||||||
if (mContent == null) {
|
if (mContent == null) {
|
||||||
return super.hitTest(src);
|
return super.hitTest(src);
|
||||||
}
|
}
|
||||||
if (mPath == null || !mInvertible) {
|
if (mPath == null || !mInvertible || !mTransformInvertible) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
float[] dst = new float[2];
|
float[] dst = new float[2];
|
||||||
mInvMatrix.mapPoints(dst, src);
|
mInvMatrix.mapPoints(dst, src);
|
||||||
|
mInvTransform.mapPoints(dst, src);
|
||||||
int x = Math.round(dst[0]);
|
int x = Math.round(dst[0]);
|
||||||
int y = Math.round(dst[1]);
|
int y = Math.round(dst[1]);
|
||||||
|
|
||||||
|
|||||||
@@ -81,12 +81,13 @@ class UseView extends RenderableView {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
int hitTest(float[] src) {
|
int hitTest(float[] src) {
|
||||||
if (!mInvertible) {
|
if (!mInvertible || !mTransformInvertible) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
float[] dst = new float[2];
|
float[] dst = new float[2];
|
||||||
mInvMatrix.mapPoints(dst, src);
|
mInvMatrix.mapPoints(dst, src);
|
||||||
|
mInvTransform.mapPoints(dst, src);
|
||||||
|
|
||||||
VirtualView template = getSvgView().getDefinedTemplate(mHref);
|
VirtualView template = getSvgView().getDefinedTemplate(mHref);
|
||||||
int hitChild = template.hitTest(dst);
|
int hitChild = template.hitTest(dst);
|
||||||
|
|||||||
@@ -62,7 +62,9 @@ abstract public class VirtualView extends ViewGroup {
|
|||||||
Matrix mMatrix = new Matrix();
|
Matrix mMatrix = new Matrix();
|
||||||
Matrix mTransform = new Matrix();
|
Matrix mTransform = new Matrix();
|
||||||
Matrix mInvMatrix = new Matrix();
|
Matrix mInvMatrix = new Matrix();
|
||||||
|
Matrix mInvTransform = new Matrix();
|
||||||
boolean mInvertible = true;
|
boolean mInvertible = true;
|
||||||
|
boolean mTransformInvertible = true;
|
||||||
private RectF mClientRect;
|
private RectF mClientRect;
|
||||||
|
|
||||||
private int mClipRule;
|
private int mClipRule;
|
||||||
|
|||||||
@@ -81,8 +81,7 @@
|
|||||||
{
|
{
|
||||||
CGRect clipBounds = CGContextGetClipBoundingBox(context);
|
CGRect clipBounds = CGContextGetClipBoundingBox(context);
|
||||||
clipBounds = CGRectApplyAffineTransform(clipBounds, self.matrix);
|
clipBounds = CGRectApplyAffineTransform(clipBounds, self.matrix);
|
||||||
CGAffineTransform transform = CATransform3DGetAffineTransform(self.layer.transform);
|
clipBounds = CGRectApplyAffineTransform(clipBounds, self.transform);
|
||||||
clipBounds = CGRectApplyAffineTransform(clipBounds, transform);
|
|
||||||
CGFloat width = CGRectGetWidth(clipBounds);
|
CGFloat width = CGRectGetWidth(clipBounds);
|
||||||
CGFloat height = CGRectGetHeight(clipBounds);
|
CGFloat height = CGRectGetHeight(clipBounds);
|
||||||
|
|
||||||
@@ -128,6 +127,7 @@
|
|||||||
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||||
{
|
{
|
||||||
CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix);
|
CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix);
|
||||||
|
transformed = CGPointApplyAffineTransform(transformed, self.invTransform);
|
||||||
|
|
||||||
if (self.clipPath) {
|
if (self.clipPath) {
|
||||||
RNSVGClipPath *clipNode = (RNSVGClipPath*)[self.svgView getDefinedClipPath:self.clipPath];
|
RNSVGClipPath *clipNode = (RNSVGClipPath*)[self.svgView getDefinedClipPath:self.clipPath];
|
||||||
|
|||||||
+21
-22
@@ -211,30 +211,29 @@
|
|||||||
|
|
||||||
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||||
{
|
{
|
||||||
|
CGPoint transformed = point;
|
||||||
if (self.align) {
|
if (self.align) {
|
||||||
CGPoint transformed = CGPointApplyAffineTransform(point, _invviewBoxTransform);
|
transformed = CGPointApplyAffineTransform(transformed, _invviewBoxTransform);
|
||||||
for (RNSVGNode *node in [self.subviews reverseObjectEnumerator]) {
|
|
||||||
if (![node isKindOfClass:[RNSVGNode class]]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event) {
|
|
||||||
node.active = NO;
|
|
||||||
} else if (node.active) {
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
UIView *hitChild = [node hitTest:transformed withEvent:event];
|
|
||||||
|
|
||||||
if (hitChild) {
|
|
||||||
node.active = YES;
|
|
||||||
return (node.responsible || (node != hitChild)) ? hitChild : self;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil;
|
|
||||||
} else {
|
|
||||||
return [super hitTest:point withEvent:event];
|
|
||||||
}
|
}
|
||||||
|
for (RNSVGNode *node in [self.subviews reverseObjectEnumerator]) {
|
||||||
|
if (![node isKindOfClass:[RNSVGNode class]]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event) {
|
||||||
|
node.active = NO;
|
||||||
|
} else if (node.active) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
UIView *hitChild = [node hitTest:transformed withEvent:event];
|
||||||
|
|
||||||
|
if (hitChild) {
|
||||||
|
node.active = YES;
|
||||||
|
return (node.responsible || (node != hitChild)) ? hitChild : self;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
|
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
|
||||||
const CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix);
|
CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix);
|
||||||
|
transformed = CGPointApplyAffineTransform(transformed, self.invTransform);
|
||||||
RNSVGNode const* template = [self.svgView getDefinedTemplate:self.href];
|
RNSVGNode const* template = [self.svgView getDefinedTemplate:self.href];
|
||||||
if (event) {
|
if (event) {
|
||||||
self.active = NO;
|
self.active = NO;
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ extern CGFloat const RNSVG_DEFAULT_FONT_SIZE;
|
|||||||
@property (nonatomic, assign) BOOL responsible;
|
@property (nonatomic, assign) BOOL responsible;
|
||||||
@property (nonatomic, assign) CGAffineTransform matrix;
|
@property (nonatomic, assign) CGAffineTransform matrix;
|
||||||
@property (nonatomic, assign) CGAffineTransform invmatrix;
|
@property (nonatomic, assign) CGAffineTransform invmatrix;
|
||||||
|
@property (nonatomic, assign) CGAffineTransform invTransform;
|
||||||
@property (nonatomic, assign) BOOL active;
|
@property (nonatomic, assign) BOOL active;
|
||||||
@property (nonatomic, assign) CGPathRef path;
|
@property (nonatomic, assign) CGPathRef path;
|
||||||
@property (nonatomic, assign) CGRect clientRect;
|
@property (nonatomic, assign) CGRect clientRect;
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
|||||||
{
|
{
|
||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
self.opacity = 1;
|
self.opacity = 1;
|
||||||
|
self.invTransform = CGAffineTransformIdentity;
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,8 +169,7 @@ UInt32 saturate(CGFloat value) {
|
|||||||
// This needs to be painted on a layer before being composited.
|
// This needs to be painted on a layer before being composited.
|
||||||
CGContextSaveGState(context);
|
CGContextSaveGState(context);
|
||||||
CGContextConcatCTM(context, self.matrix);
|
CGContextConcatCTM(context, self.matrix);
|
||||||
CGAffineTransform transform = CATransform3DGetAffineTransform(self.layer.transform);
|
CGContextConcatCTM(context, self.transform);
|
||||||
CGContextConcatCTM(context, transform);
|
|
||||||
CGContextSetAlpha(context, self.opacity);
|
CGContextSetAlpha(context, self.opacity);
|
||||||
|
|
||||||
[self beginTransparencyLayer:context];
|
[self beginTransparencyLayer:context];
|
||||||
@@ -421,6 +420,7 @@ UInt32 saturate(CGFloat value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix);
|
CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix);
|
||||||
|
transformed = CGPointApplyAffineTransform(transformed, self.invTransform);
|
||||||
|
|
||||||
BOOL evenodd = self.fillRule == kRNSVGCGFCRuleEvenodd;
|
BOOL evenodd = self.fillRule == kRNSVGCGFCRuleEvenodd;
|
||||||
if (!CGPathContainsPoint(_hitArea, nil, transformed, evenodd) &&
|
if (!CGPathContainsPoint(_hitArea, nil, transformed, evenodd) &&
|
||||||
|
|||||||
@@ -156,9 +156,10 @@ RCT_EXPORT_VIEW_PROPERTY(opacity, CGFloat)
|
|||||||
RCT_EXPORT_VIEW_PROPERTY(matrix, CGAffineTransform)
|
RCT_EXPORT_VIEW_PROPERTY(matrix, CGAffineTransform)
|
||||||
RCT_CUSTOM_VIEW_PROPERTY(transform, CATransform3D, RNSVGNode)
|
RCT_CUSTOM_VIEW_PROPERTY(transform, CATransform3D, RNSVGNode)
|
||||||
{
|
{
|
||||||
view.layer.transform = json ? [RNSVGNodeManager CATransform3D:json] : defaultView.layer.transform;
|
CATransform3D transform3d = json ? [RNSVGNodeManager CATransform3D:json] : defaultView.layer.transform;
|
||||||
// TODO: Improve this by enabling edge antialiasing only for transforms with rotation or skewing
|
CGAffineTransform transform = CATransform3DGetAffineTransform(transform3d);
|
||||||
view.layer.allowsEdgeAntialiasing = !CATransform3DIsIdentity(view.layer.transform);
|
view.invTransform = CGAffineTransformInvert(transform);
|
||||||
|
view.transform = transform;
|
||||||
[view invalidate];
|
[view invalidate];
|
||||||
}
|
}
|
||||||
RCT_EXPORT_VIEW_PROPERTY(mask, NSString)
|
RCT_EXPORT_VIEW_PROPERTY(mask, NSString)
|
||||||
|
|||||||
Reference in New Issue
Block a user