mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-23 15:45:24 +00:00
First attempt at nested svg support.
This commit is contained in:
@@ -12,6 +12,8 @@ package com.horcrux.svg;
|
|||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
|
|
||||||
|
import com.facebook.react.uimanager.LayoutShadowNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shadow node for virtual Defs view
|
* Shadow node for virtual Defs view
|
||||||
*/
|
*/
|
||||||
@@ -20,9 +22,13 @@ class DefsShadowNode extends DefinitionShadowNode {
|
|||||||
@Override
|
@Override
|
||||||
public void draw(Canvas canvas, Paint paint, float opacity) {
|
public void draw(Canvas canvas, Paint paint, float opacity) {
|
||||||
NodeRunnable markUpdateSeenRecursive = new NodeRunnable() {
|
NodeRunnable markUpdateSeenRecursive = new NodeRunnable() {
|
||||||
public void run(VirtualNode node) {
|
public void run(LayoutShadowNode node) {
|
||||||
node.markUpdateSeen();
|
node.markUpdateSeen();
|
||||||
node.traverseChildren(this);
|
if (node instanceof VirtualNode) {
|
||||||
|
((VirtualNode) node).traverseChildren(this);
|
||||||
|
} else if (node instanceof SvgViewShadowNode) {
|
||||||
|
((SvgViewShadowNode) node).traverseChildren(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
traverseChildren(markUpdateSeenRecursive);
|
traverseChildren(markUpdateSeenRecursive);
|
||||||
@@ -30,8 +36,10 @@ class DefsShadowNode extends DefinitionShadowNode {
|
|||||||
|
|
||||||
void saveDefinition() {
|
void saveDefinition() {
|
||||||
traverseChildren(new NodeRunnable() {
|
traverseChildren(new NodeRunnable() {
|
||||||
public void run(VirtualNode node) {
|
public void run(LayoutShadowNode node) {
|
||||||
node.saveDefinition();
|
if (node instanceof VirtualNode) {
|
||||||
|
((VirtualNode)node).saveDefinition();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import android.graphics.Point;
|
|||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
|
|
||||||
import com.facebook.react.bridge.ReadableMap;
|
import com.facebook.react.bridge.ReadableMap;
|
||||||
|
import com.facebook.react.uimanager.LayoutShadowNode;
|
||||||
import com.facebook.react.uimanager.ReactShadowNode;
|
import com.facebook.react.uimanager.ReactShadowNode;
|
||||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||||
|
|
||||||
@@ -72,23 +73,29 @@ class GroupShadowNode extends RenderableShadowNode {
|
|||||||
final SvgViewShadowNode svg = getSvgShadowNode();
|
final SvgViewShadowNode svg = getSvgShadowNode();
|
||||||
final GroupShadowNode self = this;
|
final GroupShadowNode self = this;
|
||||||
traverseChildren(new NodeRunnable() {
|
traverseChildren(new NodeRunnable() {
|
||||||
public void run(VirtualNode node) {
|
public void run(LayoutShadowNode lNode) {
|
||||||
if (node instanceof RenderableShadowNode) {
|
if (lNode instanceof VirtualNode) {
|
||||||
((RenderableShadowNode)node).mergeProperties(self);
|
VirtualNode node = ((VirtualNode)lNode);
|
||||||
}
|
if (node instanceof RenderableShadowNode) {
|
||||||
|
((RenderableShadowNode)node).mergeProperties(self);
|
||||||
|
}
|
||||||
|
|
||||||
int count = node.saveAndSetupCanvas(canvas);
|
int count = node.saveAndSetupCanvas(canvas);
|
||||||
node.draw(canvas, paint, opacity * mOpacity);
|
node.draw(canvas, paint, opacity * mOpacity);
|
||||||
node.restoreCanvas(canvas, count);
|
node.restoreCanvas(canvas, count);
|
||||||
|
|
||||||
if (node instanceof RenderableShadowNode) {
|
if (node instanceof RenderableShadowNode) {
|
||||||
((RenderableShadowNode)node).resetProperties();
|
((RenderableShadowNode)node).resetProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
node.markUpdateSeen();
|
node.markUpdateSeen();
|
||||||
|
|
||||||
if (node.isResponsible()) {
|
if (node.isResponsible()) {
|
||||||
svg.enableTouchEvents();
|
svg.enableTouchEvents();
|
||||||
|
}
|
||||||
|
} else if (lNode instanceof SvgViewShadowNode) {
|
||||||
|
SvgViewShadowNode svgView = (SvgViewShadowNode)lNode;
|
||||||
|
svgView.drawChildren(canvas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -104,8 +111,10 @@ class GroupShadowNode extends RenderableShadowNode {
|
|||||||
final Path path = new Path();
|
final Path path = new Path();
|
||||||
|
|
||||||
traverseChildren(new NodeRunnable() {
|
traverseChildren(new NodeRunnable() {
|
||||||
public void run(VirtualNode node) {
|
public void run(LayoutShadowNode node) {
|
||||||
path.addPath(node.getPath(canvas, paint));
|
if (node instanceof VirtualNode) {
|
||||||
|
path.addPath(((VirtualNode)node).getPath(canvas, paint));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -154,8 +163,10 @@ class GroupShadowNode extends RenderableShadowNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
traverseChildren(new NodeRunnable() {
|
traverseChildren(new NodeRunnable() {
|
||||||
public void run(VirtualNode node) {
|
public void run(LayoutShadowNode node) {
|
||||||
node.saveDefinition();
|
if (node instanceof VirtualNode) {
|
||||||
|
((VirtualNode)node).saveDefinition();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -163,7 +174,7 @@ class GroupShadowNode extends RenderableShadowNode {
|
|||||||
@Override
|
@Override
|
||||||
public void resetProperties() {
|
public void resetProperties() {
|
||||||
traverseChildren(new NodeRunnable() {
|
traverseChildren(new NodeRunnable() {
|
||||||
public void run(VirtualNode node) {
|
public void run(LayoutShadowNode node) {
|
||||||
if (node instanceof RenderableShadowNode) {
|
if (node instanceof RenderableShadowNode) {
|
||||||
((RenderableShadowNode)node).resetProperties();
|
((RenderableShadowNode)node).resetProperties();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ public class SvgViewShadowNode extends LayoutShadowNode {
|
|||||||
private float mMinY;
|
private float mMinY;
|
||||||
private float mVbWidth;
|
private float mVbWidth;
|
||||||
private float mVbHeight;
|
private float mVbHeight;
|
||||||
|
private String mbbWidth;
|
||||||
|
private String mbbHeight;
|
||||||
private String mAlign;
|
private String mAlign;
|
||||||
private int mMeetOrSlice;
|
private int mMeetOrSlice;
|
||||||
private Matrix mViewBoxMatrix;
|
private Matrix mViewBoxMatrix;
|
||||||
@@ -77,6 +79,18 @@ public class SvgViewShadowNode extends LayoutShadowNode {
|
|||||||
markUpdated();
|
markUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ReactProp(name = "bbWidth")
|
||||||
|
public void setVbWidth(String bbWidth) {
|
||||||
|
mbbWidth = bbWidth;
|
||||||
|
markUpdated();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactProp(name = "bbHeight")
|
||||||
|
public void setVbHeight(String bbHeight) {
|
||||||
|
mbbHeight = bbHeight;
|
||||||
|
markUpdated();
|
||||||
|
}
|
||||||
|
|
||||||
@ReactProp(name = "align")
|
@ReactProp(name = "align")
|
||||||
public void setAlign(String align) {
|
public void setAlign(String align) {
|
||||||
mAlign = align;
|
mAlign = align;
|
||||||
@@ -117,8 +131,7 @@ public class SvgViewShadowNode extends LayoutShadowNode {
|
|||||||
(int) getLayoutHeight(),
|
(int) getLayoutHeight(),
|
||||||
Bitmap.Config.ARGB_8888);
|
Bitmap.Config.ARGB_8888);
|
||||||
|
|
||||||
mCanvas = new Canvas(bitmap);
|
drawChildren(new Canvas(bitmap));
|
||||||
drawChildren(mCanvas);
|
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,11 +139,21 @@ public class SvgViewShadowNode extends LayoutShadowNode {
|
|||||||
return mCanvas.getClipBounds();
|
return mCanvas.getClipBounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawChildren(final Canvas canvas) {
|
void drawChildren(final Canvas canvas) {
|
||||||
|
mCanvas = canvas;
|
||||||
if (mAlign != null) {
|
if (mAlign != null) {
|
||||||
RectF vbRect = getViewBox();
|
RectF vbRect = getViewBox();
|
||||||
RectF eRect = new RectF(0, 0, getLayoutWidth(), getLayoutHeight());
|
float width = getLayoutWidth();
|
||||||
|
float height = getLayoutHeight();
|
||||||
|
boolean nested = Float.isNaN(width) || Float.isNaN(height);
|
||||||
|
if (nested) {
|
||||||
|
width = Float.parseFloat(mbbWidth) * mScale;
|
||||||
|
height = Float.parseFloat(mbbHeight) * mScale;
|
||||||
|
}
|
||||||
|
RectF eRect = new RectF(0,0, width, height);
|
||||||
|
if (nested) {
|
||||||
|
canvas.clipRect(eRect);
|
||||||
|
}
|
||||||
mViewBoxMatrix = ViewBox.getTransform(vbRect, eRect, mAlign, mMeetOrSlice);
|
mViewBoxMatrix = ViewBox.getTransform(vbRect, eRect, mAlign, mMeetOrSlice);
|
||||||
canvas.concat(mViewBoxMatrix);
|
canvas.concat(mViewBoxMatrix);
|
||||||
}
|
}
|
||||||
@@ -143,20 +166,25 @@ public class SvgViewShadowNode extends LayoutShadowNode {
|
|||||||
|
|
||||||
|
|
||||||
traverseChildren(new VirtualNode.NodeRunnable() {
|
traverseChildren(new VirtualNode.NodeRunnable() {
|
||||||
public void run(VirtualNode node) {
|
public void run(LayoutShadowNode node) {
|
||||||
node.saveDefinition();
|
if (node instanceof VirtualNode) {
|
||||||
|
((VirtualNode)node).saveDefinition();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
traverseChildren(new VirtualNode.NodeRunnable() {
|
traverseChildren(new VirtualNode.NodeRunnable() {
|
||||||
public void run(VirtualNode node) {
|
public void run(LayoutShadowNode lNode) {
|
||||||
int count = node.saveAndSetupCanvas(canvas);
|
if (lNode instanceof VirtualNode) {
|
||||||
node.draw(canvas, paint, 1f);
|
VirtualNode node = (VirtualNode)lNode;
|
||||||
node.restoreCanvas(canvas, count);
|
int count = node.saveAndSetupCanvas(canvas);
|
||||||
node.markUpdateSeen();
|
node.draw(canvas, paint, 1f);
|
||||||
|
node.restoreCanvas(canvas, count);
|
||||||
|
node.markUpdateSeen();
|
||||||
|
|
||||||
if (node.isResponsible() && !mResponsible) {
|
if (node.isResponsible() && !mResponsible) {
|
||||||
mResponsible = true;
|
mResponsible = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -238,7 +266,7 @@ public class SvgViewShadowNode extends LayoutShadowNode {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
runner.run((VirtualNode) child);
|
runner.run((LayoutShadowNode) child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import android.graphics.Path;
|
|||||||
|
|
||||||
import com.facebook.react.bridge.ReadableArray;
|
import com.facebook.react.bridge.ReadableArray;
|
||||||
import com.facebook.react.bridge.ReadableMap;
|
import com.facebook.react.bridge.ReadableMap;
|
||||||
|
import com.facebook.react.uimanager.LayoutShadowNode;
|
||||||
import com.facebook.react.uimanager.ReactShadowNode;
|
import com.facebook.react.uimanager.ReactShadowNode;
|
||||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||||
|
|
||||||
@@ -177,9 +178,10 @@ class TextShadowNode extends GroupShadowNode {
|
|||||||
|
|
||||||
void releaseCachedPath() {
|
void releaseCachedPath() {
|
||||||
traverseChildren(new NodeRunnable() {
|
traverseChildren(new NodeRunnable() {
|
||||||
public void run(VirtualNode node) {
|
public void run(LayoutShadowNode node) {
|
||||||
TextShadowNode text = (TextShadowNode)node;
|
if (node instanceof TextShadowNode) {
|
||||||
text.releaseCachedPath();
|
((TextShadowNode)node).releaseCachedPath();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -308,17 +308,17 @@ abstract class VirtualNode extends LayoutShadowNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface NodeRunnable {
|
interface NodeRunnable {
|
||||||
void run(VirtualNode node);
|
void run(LayoutShadowNode node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void traverseChildren(NodeRunnable runner) {
|
void traverseChildren(NodeRunnable runner) {
|
||||||
for (int i = 0; i < getChildCount(); i++) {
|
for (int i = 0; i < getChildCount(); i++) {
|
||||||
ReactShadowNode child = getChildAt(i);
|
ReactShadowNode child = getChildAt(i);
|
||||||
if (!(child instanceof VirtualNode)) {
|
if (!(child instanceof VirtualNode) && !(child instanceof SvgViewShadowNode)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
runner.run((VirtualNode) child);
|
runner.run((LayoutShadowNode) child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,14 +74,19 @@ class Svg extends Component{
|
|||||||
|
|
||||||
if (width && height) {
|
if (width && height) {
|
||||||
dimensions = {
|
dimensions = {
|
||||||
width: +width,
|
width: width[width.length - 1] === '%' ? width : +width,
|
||||||
height: +height,
|
height: height[height.length - 1] === '%' ? height : +height,
|
||||||
flex: 0
|
flex: 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const w = `${width}`;
|
||||||
|
const h = `${height}`;
|
||||||
|
|
||||||
return <NativeSvgView
|
return <NativeSvgView
|
||||||
{...props}
|
{...props}
|
||||||
|
bbWidth={w}
|
||||||
|
bbHeight={h}
|
||||||
{...extractViewBox({ viewBox, preserveAspectRatio })}
|
{...extractViewBox({ viewBox, preserveAspectRatio })}
|
||||||
ref={ele => {this.root = ele;}}
|
ref={ele => {this.root = ele;}}
|
||||||
style={[
|
style={[
|
||||||
@@ -98,7 +103,9 @@ class Svg extends Component{
|
|||||||
|
|
||||||
const NativeSvgView = requireNativeComponent('RNSVGSvgView', null, {
|
const NativeSvgView = requireNativeComponent('RNSVGSvgView', null, {
|
||||||
nativeOnly: {
|
nativeOnly: {
|
||||||
...ViewBoxAttributes
|
...ViewBoxAttributes,
|
||||||
|
width: true,
|
||||||
|
height: true,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,9 @@
|
|||||||
- (void)parseReference
|
- (void)parseReference
|
||||||
{
|
{
|
||||||
[self traverseSubviews:^(RNSVGNode *node) {
|
[self traverseSubviews:^(RNSVGNode *node) {
|
||||||
[node parseReference];
|
if ([node isKindOfClass:[RNSVGNode class]]) {
|
||||||
|
[node parseReference];
|
||||||
|
}
|
||||||
return YES;
|
return YES;
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,19 +34,29 @@
|
|||||||
{
|
{
|
||||||
[self pushGlyphContext];
|
[self pushGlyphContext];
|
||||||
RNSVGSvgView* svg = [self getSvgView];
|
RNSVGSvgView* svg = [self getSvgView];
|
||||||
[self traverseSubviews:^(RNSVGNode *node) {
|
[self traverseSubviews:^(UIView *node) {
|
||||||
if (node.responsible && !svg.responsible) {
|
if ([node isKindOfClass:[RNSVGNode class]]) {
|
||||||
svg.responsible = YES;
|
RNSVGNode* svgNode = (RNSVGNode*)node;
|
||||||
}
|
if (svgNode.responsible && !svg.responsible) {
|
||||||
|
svg.responsible = YES;
|
||||||
|
}
|
||||||
|
|
||||||
if ([node isKindOfClass:[RNSVGRenderable class]]) {
|
if ([node isKindOfClass:[RNSVGRenderable class]]) {
|
||||||
[(RNSVGRenderable*)node mergeProperties:self];
|
[(RNSVGRenderable*)node mergeProperties:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
[node renderTo:context];
|
[svgNode renderTo:context];
|
||||||
|
|
||||||
if ([node isKindOfClass:[RNSVGRenderable class]]) {
|
if ([node isKindOfClass:[RNSVGRenderable class]]) {
|
||||||
[(RNSVGRenderable*)node resetProperties];
|
[(RNSVGRenderable*)node resetProperties];
|
||||||
|
}
|
||||||
|
} else if ([node isKindOfClass:[RNSVGSvgView class]]) {
|
||||||
|
RNSVGSvgView* svgView = (RNSVGSvgView*)node;
|
||||||
|
CGRect rect = CGRectMake(0, 0, [svgView.bbWidth floatValue], [svgView.bbHeight floatValue]);
|
||||||
|
CGContextClipToRect(context, rect);
|
||||||
|
[svgView drawToContext:context withRect:(CGRect)rect];
|
||||||
|
} else {
|
||||||
|
RCTLogWarn(@"Not a RNSVGNode: %@", node.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
@@ -89,8 +99,10 @@
|
|||||||
{
|
{
|
||||||
CGMutablePathRef __block path = CGPathCreateMutable();
|
CGMutablePathRef __block path = CGPathCreateMutable();
|
||||||
[self traverseSubviews:^(RNSVGNode *node) {
|
[self traverseSubviews:^(RNSVGNode *node) {
|
||||||
CGAffineTransform transform = node.matrix;
|
if ([node isKindOfClass:[RNSVGNode class]]) {
|
||||||
CGPathAddPath(path, &transform, [node getPath:context]);
|
CGAffineTransform transform = node.matrix;
|
||||||
|
CGPathAddPath(path, &transform, [node getPath:context]);
|
||||||
|
}
|
||||||
return YES;
|
return YES;
|
||||||
}];
|
}];
|
||||||
|
|
||||||
@@ -147,7 +159,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
[self traverseSubviews:^(__kindof RNSVGNode *node) {
|
[self traverseSubviews:^(__kindof RNSVGNode *node) {
|
||||||
[node parseReference];
|
if ([node isKindOfClass:[RNSVGNode class]]) {
|
||||||
|
[node parseReference];
|
||||||
|
}
|
||||||
return YES;
|
return YES;
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
@interface RNSVGSvgView : UIView <RNSVGContainer>
|
@interface RNSVGSvgView : UIView <RNSVGContainer>
|
||||||
|
|
||||||
|
@property (nonatomic, strong) NSString *bbWidth;
|
||||||
|
@property (nonatomic, strong) NSString *bbHeight;
|
||||||
@property (nonatomic, assign) CGFloat minX;
|
@property (nonatomic, assign) CGFloat minX;
|
||||||
@property (nonatomic, assign) CGFloat minY;
|
@property (nonatomic, assign) CGFloat minY;
|
||||||
@property (nonatomic, assign) CGFloat vbWidth;
|
@property (nonatomic, assign) CGFloat vbWidth;
|
||||||
@@ -22,6 +24,8 @@
|
|||||||
@property (nonatomic, strong) NSString *align;
|
@property (nonatomic, strong) NSString *align;
|
||||||
@property (nonatomic, assign) RNSVGVBMOS meetOrSlice;
|
@property (nonatomic, assign) RNSVGVBMOS meetOrSlice;
|
||||||
@property (nonatomic, assign) BOOL responsible;
|
@property (nonatomic, assign) BOOL responsible;
|
||||||
|
@property (nonatomic, assign) CGRect boundingBox;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* define <ClipPath></ClipPath> content as clipPath template.
|
* define <ClipPath></ClipPath> content as clipPath template.
|
||||||
@@ -42,4 +46,8 @@
|
|||||||
|
|
||||||
- (CGRect)getContextBounds;
|
- (CGRect)getContextBounds;
|
||||||
|
|
||||||
|
- (void)drawRect:(CGRect)rect;
|
||||||
|
|
||||||
|
- (void)drawToContext:(CGContextRef)context withRect:(CGRect)rect;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
NSMutableDictionary<NSString *, RNSVGNode *> *_clipPaths;
|
NSMutableDictionary<NSString *, RNSVGNode *> *_clipPaths;
|
||||||
NSMutableDictionary<NSString *, RNSVGNode *> *_templates;
|
NSMutableDictionary<NSString *, RNSVGNode *> *_templates;
|
||||||
NSMutableDictionary<NSString *, RNSVGPainter *> *_painters;
|
NSMutableDictionary<NSString *, RNSVGPainter *> *_painters;
|
||||||
CGRect _boundingBox;
|
|
||||||
CGAffineTransform _viewBoxTransform;
|
CGAffineTransform _viewBoxTransform;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,6 +82,26 @@
|
|||||||
_vbHeight = vbHeight;
|
_vbHeight = vbHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setBBWidth:(NSString *)bbWidth
|
||||||
|
{
|
||||||
|
if ([bbWidth isEqualToString:_bbWidth]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[self invalidate];
|
||||||
|
_bbWidth = bbWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setBBHeight:(NSString *)bbHeight
|
||||||
|
{
|
||||||
|
if ([bbHeight isEqualToString:_bbHeight]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[self invalidate];
|
||||||
|
_bbHeight = bbHeight;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setAlign:(NSString *)align
|
- (void)setAlign:(NSString *)align
|
||||||
{
|
{
|
||||||
if ([align isEqualToString:_align]) {
|
if ([align isEqualToString:_align]) {
|
||||||
@@ -103,13 +122,7 @@
|
|||||||
_meetOrSlice = meetOrSlice;
|
_meetOrSlice = meetOrSlice;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)drawRect:(CGRect)rect
|
- (void)drawToContext:(CGContextRef)context withRect:(CGRect)rect {
|
||||||
{
|
|
||||||
_clipPaths = nil;
|
|
||||||
_templates = nil;
|
|
||||||
_painters = nil;
|
|
||||||
_boundingBox = rect;
|
|
||||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
|
||||||
|
|
||||||
if (self.align) {
|
if (self.align) {
|
||||||
_viewBoxTransform = [RNSVGViewBox getTransform:CGRectMake(self.minX, self.minY, self.vbWidth, self.vbHeight)
|
_viewBoxTransform = [RNSVGViewBox getTransform:CGRectMake(self.minX, self.minY, self.vbWidth, self.vbHeight)
|
||||||
@@ -119,21 +132,36 @@
|
|||||||
CGContextConcatCTM(context, _viewBoxTransform);
|
CGContextConcatCTM(context, _viewBoxTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (RNSVGNode *node in self.subviews) {
|
for (UIView *node in self.subviews) {
|
||||||
if ([node isKindOfClass:[RNSVGNode class]]) {
|
if ([node isKindOfClass:[RNSVGNode class]]) {
|
||||||
if (node.responsible && !self.responsible) {
|
RNSVGNode *svg = (RNSVGNode *)node;
|
||||||
|
[svg renderTo:context];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)drawRect:(CGRect)rect
|
||||||
|
{
|
||||||
|
_clipPaths = nil;
|
||||||
|
_templates = nil;
|
||||||
|
_painters = nil;
|
||||||
|
_boundingBox = rect;
|
||||||
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||||
|
|
||||||
|
for (UIView *node in self.subviews) {
|
||||||
|
if ([node isKindOfClass:[RNSVGNode class]]) {
|
||||||
|
RNSVGNode *svg = (RNSVGNode *)node;
|
||||||
|
if (svg.responsible && !self.responsible) {
|
||||||
self.responsible = YES;
|
self.responsible = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
[node parseReference];
|
[svg parseReference];
|
||||||
|
} else {
|
||||||
|
RCTLogWarn(@"Not a RNSVGNode: %@", node.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (RNSVGNode *node in self.subviews) {
|
[self drawToContext:context withRect:rect];
|
||||||
if ([node isKindOfClass:[RNSVGNode class]]) {
|
|
||||||
[node renderTo:context];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||||
|
|||||||
@@ -103,6 +103,6 @@ extern CGFloat const RNSVG_DEFAULT_FONT_SIZE;
|
|||||||
|
|
||||||
- (void)endTransparencyLayer:(CGContextRef)context;
|
- (void)endTransparencyLayer:(CGContextRef)context;
|
||||||
|
|
||||||
- (void)traverseSubviews:(BOOL (^)(__kindof RNSVGNode *node))block;
|
- (void)traverseSubviews:(BOOL (^)(__kindof UIView *node))block;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -310,13 +310,19 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)traverseSubviews:(BOOL (^)(__kindof RNSVGNode *node))block
|
- (void)traverseSubviews:(BOOL (^)(__kindof UIView *node))block
|
||||||
{
|
{
|
||||||
for (RNSVGNode *node in self.subviews) {
|
for (UIView *node in self.subviews) {
|
||||||
if ([node isKindOfClass:[RNSVGNode class]]) {
|
if ([node isKindOfClass:[RNSVGNode class]]) {
|
||||||
if (!block(node)) {
|
if (!block(node)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if ([node isKindOfClass:[RNSVGSvgView class]]) {
|
||||||
|
if (!block(node)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RCTLogWarn(@"Not a RNSVGNode: %@", node.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ RCT_EXPORT_MODULE()
|
|||||||
return [RNSVGSvgView new];
|
return [RNSVGSvgView new];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_VIEW_PROPERTY(bbWidth, NSString)
|
||||||
|
RCT_EXPORT_VIEW_PROPERTY(bbHeight, NSString)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(minX, CGFloat)
|
RCT_EXPORT_VIEW_PROPERTY(minX, CGFloat)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(minY, CGFloat)
|
RCT_EXPORT_VIEW_PROPERTY(minY, CGFloat)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(vbWidth, CGFloat)
|
RCT_EXPORT_VIEW_PROPERTY(vbWidth, CGFloat)
|
||||||
|
|||||||
Reference in New Issue
Block a user