fix touch events within the elements which are nested in G

This commit is contained in:
Horcrux
2016-08-06 21:37:58 +08:00
parent 76a51f1f47
commit 7f4eb47f81
17 changed files with 123 additions and 121 deletions

View File

@@ -56,6 +56,8 @@ class HoverExample extends Component {
render () {
return <Svg height="120" width="120">
<G>
<G>
<Path
d="M50,5L20,99L95,39L5,39L80,99z"
stroke={this.state.hover ? 'rgba(10, 10, 10, 0.5)' : 'black'}
@@ -65,9 +67,12 @@ class HoverExample extends Component {
onPressIn={this.toggle}
onPressOut={this.toggle}
x="0"
y="10"
scale="0.5"
y="0"
scale="1.2"
opacity="0.3"
/>
</G>
</G>
</Svg>;
}
}
@@ -82,12 +87,14 @@ class GroupExample extends Component {
viewBox="0 0 240 240"
>
<G>
<G onPress={() => alert('Pressed')}>
<Circle cx="80" cy="80" r="30" fill="green" x="20" />
<Rect x="20" y="20" width="40" height="40" fill="yellow"/>
<G scale="1.4">
<G>
<Circle cx="80" cy="80" r="30" fill="green" x="20" scale="1.2" onPress={() => alert('Pressed')}/>
<Rect x="20" y="20" width="40" height="40" fill="yellow" />
<Text fontWeight="bold" fontSize="40" x="100" y="100" scale="2">H</Text>
</G>
</G>
</G>
</Svg>;
}

View File

@@ -73,8 +73,7 @@ class Svg extends Component{
const nativeProps = _.omit(props, ['width', 'height', 'viewBox', 'preserveAspectRatio', 'opacity']);
return (
<NativeSvgView
return <NativeSvgView
{...nativeProps}
ref={ele => {this.root = ele;}}
style={[
@@ -87,8 +86,7 @@ class Svg extends Component{
]}
>
{content}
</NativeSvgView>
);
</NativeSvgView>;
}
}

View File

@@ -14,7 +14,4 @@
#import "RNSVGRenderable.h"
@interface RNSVGGroup : RNSVGRenderable <RNSVGContainer>
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
@end

View File

@@ -21,7 +21,7 @@
[node renderTo:context];
if (node.responsible && !svg.responsible) {
self.responsible = YES;
svg.responsible = YES;
}
}
}
@@ -32,21 +32,33 @@
CGMutablePathRef path = CGPathCreateMutable();
for (RNSVGNode *node in self.subviews) {
if ([node isKindOfClass:[RNSVGNode class]]) {
CGAffineTransform transform = node.transform;
CGAffineTransform transform = node.matrix;
CGPathAddPath(path, &transform, [node getPath:context]);
}
}
return (CGPathRef)CFAutorelease(path);
}
// hitTest delagate
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event withTransform:(CGAffineTransform)transform
{
CGAffineTransform matrix = CGAffineTransformConcat(self.matrix, transform);
for (RNSVGNode *node in [self.subviews reverseObjectEnumerator]) {
if ([node isKindOfClass:[RNSVGNode class]]) {
UIView *view = [node hitTest: point withEvent:event];
if (event) {
node.active = NO;
}
if (node.active) {
return node;
}
UIView *view = [node hitTest: point withEvent:event withTransform:matrix];
if (view) {
if (node.responsible || node != view) {
node.active = YES;
if (node.responsible || (node != view)) {
return view;
} else {
return self;

View File

@@ -71,10 +71,7 @@
{
CGRect rect = [self getRect:context];
// add hit area
self.hitArea = CGPathCreateMutable();
CGPathRef path = CGPathCreateWithRect(rect, nil);
CGPathAddPath(self.hitArea, nil, path);
CGPathRelease(path);
self.hitArea = CGPathCreateWithRect(rect, nil);
[self clip:context];
CGContextSaveGState(context);
@@ -97,9 +94,7 @@
- (CGPathRef)getPath:(CGContextRef)context
{
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, nil, [self getRect:context]);
return (CGPathRef)CFAutorelease(path);
return CGPathCreateWithRect([self getRect:context], nil);
}
@end

View File

@@ -15,6 +15,7 @@
if (d == _d) {
return;
}
[self invalidate];
CGPathRelease(_d);
_d = CGPathRetain(d);
@@ -27,20 +28,25 @@
- (void)renderLayerTo:(CGContextRef)context
{
if ((!self.fill && !self.stroke) || !self.d) {
CGPathRef path = [self getPath:context];
if ((!self.fill && !self.stroke) || !path) {
return;
}
// Add path to hitArea
self.hitArea = CGPathCreateMutableCopy(_d);
CGMutablePathRef hitArea = CGPathCreateMutableCopy(path);
if (self.stroke) {
// Add stroke to hitArea
CGPathRef strokePath = CGPathCreateCopyByStrokingPath(_d, nil, self.strokeWidth, self.strokeLinecap, self.strokeLinejoin, self.strokeMiterlimit);
CGPathAddPath(self.hitArea, nil, strokePath);
CGPathRef strokePath = CGPathCreateCopyByStrokingPath(hitArea, nil, self.strokeWidth, self.strokeLinecap, self.strokeLinejoin, self.strokeMiterlimit);
CGPathAddPath(hitArea, nil, strokePath);
CGPathRelease(strokePath);
}
CGAffineTransform transform = self.matrix;
self.hitArea = CGPathCreateCopyByTransformingPath(hitArea, &transform);
CGPathRelease(hitArea);
if (self.opacity == 0) {
return;
}
@@ -56,7 +62,7 @@
[self clip:context];
CGContextSaveGState(context);
CGContextAddPath(context, self.d);
CGContextAddPath(context, path);
CGContextClip(context);
RNSVGBrushConverter *brushConverter = [[self getSvgView] getDefinedBrushConverter:[self.fill brushRef]];
[self.fill paint:context opacity:self.fillOpacity brushConverter:brushConverter];
@@ -78,7 +84,7 @@
}
if (!fillColor) {
CGContextAddPath(context, self.d);
CGContextAddPath(context, path);
CGContextReplacePathWithStrokedPath(context);
CGContextClip(context);
}
@@ -92,11 +98,11 @@
} else {
// draw fill
[self clip:context];
CGContextAddPath(context, self.d);
CGContextAddPath(context, path);
CGContextDrawPath(context, mode);
// draw stroke
CGContextAddPath(context, self.d);
CGContextAddPath(context, path);
CGContextReplacePathWithStrokedPath(context);
CGContextClip(context);
RNSVGBrushConverter *brushConverter = [[self getSvgView] getDefinedBrushConverter:[self.stroke brushRef]];
@@ -106,7 +112,7 @@
}
[self clip:context];
CGContextAddPath(context, self.d);
CGContextAddPath(context, path);
CGContextDrawPath(context, mode);
}

View File

@@ -24,6 +24,7 @@
@property (nonatomic, strong) NSString *clipPathRef; // use clipPath="url(#clip)" as ClipPath
@property (nonatomic, assign) BOOL responsible;
@property (nonatomic, assign) CGAffineTransform matrix;
@property (nonatomic, assign) BOOL active;
- (void)invalidate;
@@ -52,7 +53,7 @@
/**
* run hitTest
*/
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event withTransform:(CGAffineTransform)transfrom;
- (RNSVGSvgView *)getSvgView;

View File

@@ -69,12 +69,6 @@
_opacity = opacity;
}
- (void)setMatrix:(CGAffineTransform)matrix
{
self.transform = matrix;
[self invalidate];
}
- (void)setClipPath:(CGPathRef)clipPath
{
if (_clipPath == clipPath) {
@@ -147,7 +141,15 @@
// abstract
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
// hitTest delagate
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
// abstract
return nil;
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event withTransform:(CGAffineTransform)transfrom
{
// abstract
return nil;

View File

@@ -26,7 +26,7 @@
@property (nonatomic, assign) CGFloat strokeMiterlimit;
@property (nonatomic, assign) RNSVGCGFloatArray strokeDasharray;
@property (nonatomic, assign) CGFloat strokeDashoffset;
@property (nonatomic, assign) CGMutablePathRef hitArea;
@property (nonatomic, assign) CGPathRef hitArea;
@property (nonatomic, copy) NSArray<NSString *> *propList;
- (void)setBoundingBox:(CGContextRef)context;

View File

@@ -30,7 +30,7 @@
return self;
}
- (void)setHitArea:(CGMutablePathRef)hitArea
- (void)setHitArea:(CGPathRef)hitArea
{
if (hitArea == _hitArea) {
return;
@@ -38,7 +38,7 @@
[self invalidate];
CGPathRelease(_hitArea);
_hitArea = hitArea;
_hitArea = CGPathRetain(hitArea);
}
- (void)setFill:(RNSVGBrush *)fill
@@ -116,7 +116,7 @@
{
// This needs to be painted on a layer before being composited.
CGContextSaveGState(context);
CGContextConcatCTM(context, self.transform);
CGContextConcatCTM(context, self.matrix);
CGContextSetAlpha(context, self.opacity);
[self beginTransparencyLayer:context];
@@ -130,8 +130,22 @@
// hitTest delagate
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
return [self hitTest:point withEvent:event withTransform:CGAffineTransformMakeRotation(0)];
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event withTransform:(CGAffineTransform)transfrom
{
if (self.active) {
if (!event) {
self.active = NO;
}
return self;
}
CGPathRef hitArea = CGPathCreateCopyByTransformingPath(self.hitArea, &transfrom);
CGPathRef clipPath = self.clipPath;
if (self.hitArea && CGPathContainsPoint(self.hitArea, nil, point, NO)) {
BOOL contains = CGPathContainsPoint(hitArea, nil, point, NO);
if (contains) {
if (!clipPath) {
return self;
} else {
@@ -142,7 +156,6 @@
}
}
- (void)setBoundingBox:(CGContextRef)context
{
_boundingBox = CGContextGetClipBoundingBox(context);

View File

@@ -96,8 +96,8 @@
}
}
self.transform = CGAffineTransformScale(self.transform, scaleX, scaleY);
self.transform = CGAffineTransformTranslate(self.transform, -translateX * (_fromSymbol ? scaleX : 1), -translateY * (_fromSymbol ? scaleY : 1));
self.matrix = CGAffineTransformMakeScale(scaleX, scaleY);
self.matrix = CGAffineTransformTranslate(self.matrix, -translateX * (_fromSymbol ? scaleX : 1), -translateY * (_fromSymbol ? scaleY : 1));
[super renderTo:context];
}

View File

@@ -38,12 +38,6 @@
_r = r;
}
- (void)renderLayerTo:(CGContextRef)context
{
self.d = [self getPath: context];
[super renderLayerTo:context];
}
- (CGPathRef)getPath:(CGContextRef)context
{
[self setBoundingBox:context];

View File

@@ -47,12 +47,6 @@
_ry = ry;
}
- (void)renderLayerTo:(CGContextRef)context
{
self.d = [self getPath: context];
[super renderLayerTo:context];
}
- (CGPathRef)getPath:(CGContextRef)context
{
[self setBoundingBox:context];

View File

@@ -47,12 +47,6 @@
_y2 = y2;
}
- (void)renderLayerTo:(CGContextRef)context
{
self.d = [self getPath: context];
[super renderLayerTo:context];
}
- (CGPathRef)getPath:(CGContextRef)context
{
[self setBoundingBox:context];

View File

@@ -65,12 +65,6 @@
_ry = ry;
}
- (void)renderLayerTo:(CGContextRef)context
{
self.d = [self getPath: context];
[super renderLayerTo:context];
}
- (CGPathRef)getPath:(CGContextRef)context
{
[self setBoundingBox:context];

View File

@@ -53,12 +53,6 @@ static void RNSVGFreeTextFrame(RNSVGTextFrame frame)
RNSVGFreeTextFrame(_textFrame);
}
- (void)renderLayerTo:(CGContextRef)context
{
self.d = [self getPath: context];
[super renderLayerTo:context];
}
- (CGPathRef)getPath:(CGContextRef)context
{
CGMutablePathRef path = CGPathCreateMutable();
@@ -124,6 +118,7 @@ static void RNSVGFreeTextFrame(RNSVGTextFrame frame)
transform = CGAffineTransformTranslate(upsideDown, point.x, point.y);
}
CGPathAddPath(path, &transform, letter);
}

View File

@@ -26,7 +26,7 @@
#define NEXT_VALUE [self double:arr[i++]]
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, 0, 0);
CGPathMoveToPoint(path, nil, 0, 0);
@try {
NSUInteger i = 0;
@@ -34,28 +34,28 @@
NSUInteger type = [arr[i++] unsignedIntegerValue];
switch (type) {
case 0:
CGPathMoveToPoint(path, NULL, NEXT_VALUE, NEXT_VALUE);
CGPathMoveToPoint(path, nil, NEXT_VALUE, NEXT_VALUE);
break;
case 1:
CGPathCloseSubpath(path);
break;
case 2:
CGPathAddLineToPoint(path, NULL, NEXT_VALUE, NEXT_VALUE);
CGPathAddLineToPoint(path, nil, NEXT_VALUE, NEXT_VALUE);
break;
case 3:
CGPathAddCurveToPoint(path, NULL, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE);
CGPathAddCurveToPoint(path, nil, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE);
break;
default:
RCTLogError(@"Invalid CGPath type %zd at element %zd of %@", type, i, arr);
CGPathRelease(path);
return NULL;
return nil;
}
}
}
@catch (NSException *exception) {
RCTLogError(@"Invalid CGPath format: %@", arr);
CGPathRelease(path);
return NULL;
return nil;
}
return (CGPathRef)CFAutorelease(path);
@@ -123,7 +123,7 @@ RCT_ENUM_CONVERTER(RNSVGVBMOS, (@{
CFRelease(attrString);
frame.lines[i] = line;
frame.widths[i] = CTLineGetTypographicBounds(line, NULL, NULL, NULL);
frame.widths[i] = CTLineGetTypographicBounds(line, nil, nil, nil);
}];
return frame;
@@ -136,7 +136,7 @@ RCT_ENUM_CONVERTER(RNSVGVBMOS, (@{
RNSVGCGFloatArray array;
array.count = count;
array.array = NULL;
array.array = nil;
if (count) {
// Ideally, these arrays should already use the same memory layout.
@@ -213,13 +213,13 @@ RCT_ENUM_CONVERTER(RNSVGVBMOS, (@{
break;
default:
RCTLogError(@"Invalid RNSVGBezier type %zd at element %zd of %@", type, i, arr);
return NULL;
return nil;
}
}
}
@catch (NSException *exception) {
RCTLogError(@"Invalid RNSVGBezier format: %@", arr);
return NULL;
return nil;
}
return beziers;
@@ -256,7 +256,7 @@ RCT_ENUM_CONVERTER(RNSVGVBMOS, (@{
NSArray *arr = [self NSArray:json];
if (arr.count < offset + 4) {
RCTLogError(@"Too few elements in array (expected at least %zd): %@", 4 + offset, arr);
return NULL;
return nil;
}
return [self CGColor:[arr subarrayWithRange:(NSRange){offset, 4}]];
}
@@ -266,7 +266,7 @@ RCT_ENUM_CONVERTER(RNSVGVBMOS, (@{
NSArray *arr = [self NSArray:json];
if (arr.count < offset) {
RCTLogError(@"Too few elements in array (expected at least %zd): %@", offset, arr);
return NULL;
return nil;
}
arr = [arr subarrayWithRange:(NSRange){offset, arr.count - offset}];
RNSVGCGFloatArray colorsAndOffsets = [self RNSVGCGFloatArray:arr];