mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-06-03 07:06:04 +00:00
fix: marker onPress & gestures
This commit is contained in:
@@ -37,6 +37,8 @@ class MarkerView extends GroupView {
|
|||||||
String mAlign;
|
String mAlign;
|
||||||
int mMeetOrSlice;
|
int mMeetOrSlice;
|
||||||
|
|
||||||
|
Matrix markerTransform = new Matrix();
|
||||||
|
|
||||||
public MarkerView(ReactContext reactContext) {
|
public MarkerView(ReactContext reactContext) {
|
||||||
super(reactContext);
|
super(reactContext);
|
||||||
}
|
}
|
||||||
@@ -130,21 +132,19 @@ class MarkerView extends GroupView {
|
|||||||
void renderMarker(Canvas canvas, Paint paint, float opacity, RNSVGMarkerPosition position, float strokeWidth) {
|
void renderMarker(Canvas canvas, Paint paint, float opacity, RNSVGMarkerPosition position, float strokeWidth) {
|
||||||
int count = saveAndSetupCanvas(canvas, mCTM);
|
int count = saveAndSetupCanvas(canvas, mCTM);
|
||||||
|
|
||||||
|
markerTransform.reset();
|
||||||
Point origin = position.origin;
|
Point origin = position.origin;
|
||||||
Matrix transform = new Matrix();
|
markerTransform.setTranslate((float)origin.x * mScale, (float)origin.y * mScale);
|
||||||
transform.setTranslate((float)origin.x * mScale, (float)origin.y * mScale);
|
|
||||||
|
|
||||||
double markerAngle = "auto".equals(mOrient) ? -1 : Double.parseDouble(mOrient);
|
double markerAngle = "auto".equals(mOrient) ? -1 : Double.parseDouble(mOrient);
|
||||||
float degrees = 180 + (float) (markerAngle == -1 ? position.angle : markerAngle);
|
float degrees = 180 + (float) (markerAngle == -1 ? position.angle : markerAngle);
|
||||||
transform.preRotate(degrees);
|
markerTransform.preRotate(degrees);
|
||||||
|
|
||||||
boolean useStrokeWidth = "strokeWidth".equals(mMarkerUnits);
|
boolean useStrokeWidth = "strokeWidth".equals(mMarkerUnits);
|
||||||
if (useStrokeWidth) {
|
if (useStrokeWidth) {
|
||||||
transform.preScale(strokeWidth, strokeWidth);
|
markerTransform.preScale(strokeWidth, strokeWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.concat(transform);
|
|
||||||
|
|
||||||
double width = relativeOnWidth(mMarkerWidth) / mScale;
|
double width = relativeOnWidth(mMarkerWidth) / mScale;
|
||||||
double height = relativeOnHeight(mMarkerHeight) / mScale;
|
double height = relativeOnHeight(mMarkerHeight) / mScale;
|
||||||
RectF eRect = new RectF(0, 0, (float)width, (float)height);
|
RectF eRect = new RectF(0, 0, (float)width, (float)height);
|
||||||
@@ -153,12 +153,14 @@ class MarkerView extends GroupView {
|
|||||||
Matrix viewBoxMatrix = ViewBox.getTransform(vbRect, eRect, mAlign, mMeetOrSlice);
|
Matrix viewBoxMatrix = ViewBox.getTransform(vbRect, eRect, mAlign, mMeetOrSlice);
|
||||||
float[] values = new float[9];
|
float[] values = new float[9];
|
||||||
viewBoxMatrix.getValues(values);
|
viewBoxMatrix.getValues(values);
|
||||||
canvas.scale(values[Matrix.MSCALE_X], values[Matrix.MSCALE_Y]);
|
markerTransform.preScale(values[Matrix.MSCALE_X], values[Matrix.MSCALE_Y]);
|
||||||
}
|
}
|
||||||
|
|
||||||
double x = relativeOnWidth(mRefX);
|
double x = relativeOnWidth(mRefX);
|
||||||
double y = relativeOnHeight(mRefY);
|
double y = relativeOnHeight(mRefY);
|
||||||
canvas.translate((float)-x, (float)-y);
|
markerTransform.preTranslate((float)-x, (float)-y);
|
||||||
|
|
||||||
|
canvas.concat(markerTransform);
|
||||||
|
|
||||||
drawGroup(canvas, paint, opacity);
|
drawGroup(canvas, paint, opacity);
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ package com.horcrux.svg;
|
|||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.DashPathEffect;
|
import android.graphics.DashPathEffect;
|
||||||
|
import android.graphics.Matrix;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Path;
|
import android.graphics.Path;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
@@ -382,24 +383,29 @@ abstract public class RenderableView extends VirtualView {
|
|||||||
contextElement = this;
|
contextElement = this;
|
||||||
ArrayList<RNSVGMarkerPosition> positions = RNSVGMarkerPosition.fromPath(elements);
|
ArrayList<RNSVGMarkerPosition> positions = RNSVGMarkerPosition.fromPath(elements);
|
||||||
float width = (float)(this.strokeWidth != null ? relativeOnOther(this.strokeWidth) : 1);
|
float width = (float)(this.strokeWidth != null ? relativeOnOther(this.strokeWidth) : 1);
|
||||||
|
mMarkerPath = new Path();
|
||||||
for (RNSVGMarkerPosition position : positions) {
|
for (RNSVGMarkerPosition position : positions) {
|
||||||
RNSVGMarkerType type = position.type;
|
RNSVGMarkerType type = position.type;
|
||||||
|
MarkerView marker = null;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case kStartMarker:
|
case kStartMarker:
|
||||||
if (markerStart != null) markerStart.renderMarker(canvas, paint, opacity, position, width);
|
marker = markerStart;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kMidMarker:
|
case kMidMarker:
|
||||||
if (markerMid != null) markerMid.renderMarker(canvas, paint, opacity, position, width);
|
marker = markerMid;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kEndMarker:
|
case kEndMarker:
|
||||||
if (markerEnd != null) markerEnd.renderMarker(canvas, paint, opacity, position, width);
|
marker = markerEnd;
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (marker == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
marker.renderMarker(canvas, paint, opacity, position, width);
|
||||||
|
Matrix transform = marker.markerTransform;
|
||||||
|
mMarkerPath.addPath(marker.getPath(canvas, paint), transform);
|
||||||
}
|
}
|
||||||
contextElement = null;
|
contextElement = null;
|
||||||
}
|
}
|
||||||
@@ -520,9 +526,13 @@ abstract public class RenderableView extends VirtualView {
|
|||||||
if (mStrokeRegion == null && mStrokePath != null) {
|
if (mStrokeRegion == null && mStrokePath != null) {
|
||||||
mStrokeRegion = getRegion(mStrokePath);
|
mStrokeRegion = getRegion(mStrokePath);
|
||||||
}
|
}
|
||||||
|
if (mMarkerRegion == null && mMarkerPath != null) {
|
||||||
|
mMarkerRegion = getRegion(mMarkerPath);
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
(mRegion == null || !mRegion.contains(x, y)) &&
|
(mRegion == null || !mRegion.contains(x, y)) &&
|
||||||
(mStrokeRegion == null || !mStrokeRegion.contains(x, y))
|
(mStrokeRegion == null || !mStrokeRegion.contains(x, y) &&
|
||||||
|
(mMarkerRegion == null || !mMarkerRegion.contains(x, y)))
|
||||||
) {
|
) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,8 +91,10 @@ abstract public class VirtualView extends ReactViewGroup {
|
|||||||
Path mPath;
|
Path mPath;
|
||||||
Path mFillPath;
|
Path mFillPath;
|
||||||
Path mStrokePath;
|
Path mStrokePath;
|
||||||
|
Path mMarkerPath;
|
||||||
RectF mBox;
|
RectF mBox;
|
||||||
Region mRegion;
|
Region mRegion;
|
||||||
|
Region mMarkerRegion;
|
||||||
Region mStrokeRegion;
|
Region mStrokeRegion;
|
||||||
Region mClipRegion;
|
Region mClipRegion;
|
||||||
Path mClipRegionPath;
|
Path mClipRegionPath;
|
||||||
@@ -114,6 +116,7 @@ abstract public class VirtualView extends ReactViewGroup {
|
|||||||
canvasWidth = -1;
|
canvasWidth = -1;
|
||||||
fontSize = -1;
|
fontSize = -1;
|
||||||
mStrokeRegion = null;
|
mStrokeRegion = null;
|
||||||
|
mMarkerRegion = null;
|
||||||
mRegion = null;
|
mRegion = null;
|
||||||
mPath = null;
|
mPath = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,6 +140,7 @@
|
|||||||
if ([node isKindOfClass:[RNSVGNode class]] && ![node isKindOfClass:[RNSVGMask class]]) {
|
if ([node isKindOfClass:[RNSVGNode class]] && ![node isKindOfClass:[RNSVGMask class]]) {
|
||||||
CGAffineTransform transform = CGAffineTransformConcat(node.matrix, node.transforms);
|
CGAffineTransform transform = CGAffineTransformConcat(node.matrix, node.transforms);
|
||||||
CGPathAddPath(path, &transform, [node getPath:context]);
|
CGPathAddPath(path, &transform, [node getPath:context]);
|
||||||
|
CGPathAddPath(path, &transform, [node markerPath]);
|
||||||
node.dirty = false;
|
node.dirty = false;
|
||||||
}
|
}
|
||||||
return YES;
|
return YES;
|
||||||
|
|||||||
@@ -173,8 +173,6 @@ double deg2rad(CGFloat deg) {
|
|||||||
transform = CGAffineTransformScale(transform, strokeWidth, strokeWidth);
|
transform = CGAffineTransformScale(transform, strokeWidth, strokeWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
CGContextConcatCTM(context, transform);
|
|
||||||
|
|
||||||
CGFloat width = [self relativeOnWidth:self.markerWidth];
|
CGFloat width = [self relativeOnWidth:self.markerWidth];
|
||||||
CGFloat height = [self relativeOnHeight:self.markerHeight];
|
CGFloat height = [self relativeOnHeight:self.markerHeight];
|
||||||
CGRect eRect = CGRectMake(0, 0, width, height);
|
CGRect eRect = CGRectMake(0, 0, width, height);
|
||||||
@@ -183,12 +181,15 @@ double deg2rad(CGFloat deg) {
|
|||||||
eRect:eRect
|
eRect:eRect
|
||||||
align:self.align
|
align:self.align
|
||||||
meetOrSlice:self.meetOrSlice];
|
meetOrSlice:self.meetOrSlice];
|
||||||
CGContextScaleCTM(context, viewBoxTransform.a, viewBoxTransform.d);
|
transform = CGAffineTransformScale(transform, viewBoxTransform.a, viewBoxTransform.d);
|
||||||
}
|
}
|
||||||
|
|
||||||
CGFloat x = [self relativeOnWidth:self.refX];
|
CGFloat x = [self relativeOnWidth:self.refX];
|
||||||
CGFloat y = [self relativeOnHeight:self.refY];
|
CGFloat y = [self relativeOnHeight:self.refY];
|
||||||
CGContextTranslateCTM(context, -x, -y);
|
transform = CGAffineTransformTranslate(transform, -x, -y);
|
||||||
|
|
||||||
|
self.transform = transform;
|
||||||
|
CGContextConcatCTM(context, transform);
|
||||||
|
|
||||||
[self renderGroupTo:context rect:eRect];
|
[self renderGroupTo:context rect:eRect];
|
||||||
|
|
||||||
|
|||||||
@@ -45,8 +45,10 @@ extern CGFloat const RNSVG_DEFAULT_FONT_SIZE;
|
|||||||
@property (nonatomic, assign) BOOL skip;
|
@property (nonatomic, assign) BOOL skip;
|
||||||
@property (nonatomic, assign) CGPathRef path;
|
@property (nonatomic, assign) CGPathRef path;
|
||||||
@property (nonatomic, assign) CGPathRef strokePath;
|
@property (nonatomic, assign) CGPathRef strokePath;
|
||||||
|
@property (nonatomic, assign) CGPathRef markerPath;
|
||||||
@property (nonatomic, assign) CGRect clientRect;
|
@property (nonatomic, assign) CGRect clientRect;
|
||||||
@property (nonatomic, assign) CGRect pathBounds;
|
@property (nonatomic, assign) CGRect pathBounds;
|
||||||
|
@property (nonatomic, assign) CGRect markerBounds;
|
||||||
@property (nonatomic, copy) RCTDirectEventBlock onLayout;
|
@property (nonatomic, copy) RCTDirectEventBlock onLayout;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
@property (nonatomic, assign) CGFloat strokeDashoffset;
|
@property (nonatomic, assign) CGFloat strokeDashoffset;
|
||||||
@property (nonatomic, assign) RNSVGVectorEffect vectorEffect;
|
@property (nonatomic, assign) RNSVGVectorEffect vectorEffect;
|
||||||
@property (nonatomic, copy) NSArray<NSString *> *propList;
|
@property (nonatomic, copy) NSArray<NSString *> *propList;
|
||||||
|
@property (nonatomic, assign) CGPathRef hitArea;
|
||||||
|
|
||||||
- (void)setHitArea:(CGPathRef)path;
|
- (void)setHitArea:(CGPathRef)path;
|
||||||
|
|
||||||
|
|||||||
+24
-9
@@ -23,7 +23,6 @@
|
|||||||
NSArray<RNSVGLength *> *_sourceStrokeDashArray;
|
NSArray<RNSVGLength *> *_sourceStrokeDashArray;
|
||||||
CGFloat *_strokeDashArrayData;
|
CGFloat *_strokeDashArrayData;
|
||||||
CGPathRef _srcHitPath;
|
CGPathRef _srcHitPath;
|
||||||
CGPathRef _hitArea;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static RNSVGRenderable * _contextElement;
|
static RNSVGRenderable * _contextElement;
|
||||||
@@ -311,25 +310,39 @@ UInt32 saturate(CGFloat value) {
|
|||||||
_contextElement = self;
|
_contextElement = self;
|
||||||
NSArray<RNSVGMarkerPosition*>* positions = [RNSVGMarkerPosition fromCGPath:path];
|
NSArray<RNSVGMarkerPosition*>* positions = [RNSVGMarkerPosition fromCGPath:path];
|
||||||
CGFloat width = self.strokeWidth ? [self relativeOnOther:self.strokeWidth] : 1;
|
CGFloat width = self.strokeWidth ? [self relativeOnOther:self.strokeWidth] : 1;
|
||||||
|
__block CGRect bounds = CGRectNull;
|
||||||
|
CGMutablePathRef markerPath = CGPathCreateMutable();
|
||||||
for (RNSVGMarkerPosition* position in positions) {
|
for (RNSVGMarkerPosition* position in positions) {
|
||||||
RNSVGMarkerType type = [position type];
|
RNSVGMarkerType type = [position type];
|
||||||
|
RNSVGMarker *marker;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case kStartMarker:
|
case kStartMarker:
|
||||||
[markerStart renderMarker:context rect:*rect position:position strokeWidth:width];
|
marker = markerStart;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kMidMarker:
|
case kMidMarker:
|
||||||
[markerMid renderMarker:context rect:*rect position:position strokeWidth:width];
|
marker = markerMid;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kEndMarker:
|
case kEndMarker:
|
||||||
[markerEnd renderMarker:context rect:*rect position:position strokeWidth:width];
|
marker = markerEnd;
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!marker) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
[marker renderMarker:context rect:*rect position:position strokeWidth:width];
|
||||||
|
CGAffineTransform transform = marker.transform;
|
||||||
|
CGPathRef hitArea = marker.hitArea;
|
||||||
|
CGPathAddPath(markerPath, &transform, hitArea);
|
||||||
|
CGRect nodeRect = marker.pathBounds;
|
||||||
|
if (!CGRectIsEmpty(nodeRect)) {
|
||||||
|
bounds = CGRectUnion(bounds, CGRectApplyAffineTransform(nodeRect, transform));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
self.markerBounds = bounds;
|
||||||
|
self.markerPath = markerPath;
|
||||||
_contextElement = nil;
|
_contextElement = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -513,13 +526,15 @@ UInt32 saturate(CGFloat value) {
|
|||||||
CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix);
|
CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix);
|
||||||
transformed = CGPointApplyAffineTransform(transformed, self.invTransform);
|
transformed = CGPointApplyAffineTransform(transformed, self.invTransform);
|
||||||
|
|
||||||
if (!CGRectContainsPoint(self.pathBounds, transformed)) {
|
if (!CGRectContainsPoint(self.pathBounds, transformed) &&
|
||||||
|
!CGRectContainsPoint(self.markerBounds, transformed)) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL evenodd = self.fillRule == kRNSVGCGFCRuleEvenodd;
|
BOOL evenodd = self.fillRule == kRNSVGCGFCRuleEvenodd;
|
||||||
if (!CGPathContainsPoint(_hitArea, nil, transformed, evenodd) &&
|
if (!CGPathContainsPoint(_hitArea, nil, transformed, evenodd) &&
|
||||||
!CGPathContainsPoint(self.strokePath, nil, transformed, NO)) {
|
!CGPathContainsPoint(self.strokePath, nil, transformed, NO) &&
|
||||||
|
!CGPathContainsPoint(self.markerPath, nil, transformed, NO)) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user