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