finish Symbol refactor

finish Symbol refactor
finish all reusable elements refactor (iOS)
This commit is contained in:
Horcrux
2016-07-24 11:41:00 +08:00
parent 10b28434bb
commit cbea7a4edb
14 changed files with 103 additions and 49 deletions

View File

@@ -187,7 +187,6 @@
"space-in-brackets": 0, // require or disallow spaces inside brackets (off by default) "space-in-brackets": 0, // require or disallow spaces inside brackets (off by default)
"space-in-parens": 0, // require or disallow spaces inside parentheses (off by default) "space-in-parens": 0, // require or disallow spaces inside parentheses (off by default)
"space-infix-ops": 1, // require spaces around operators "space-infix-ops": 1, // require spaces around operators
"space-return-throw-case": 1, // require a space after return, throw, and case
"space-unary-ops": [1, { "words": true, "nonwords": false }], // require or disallow spaces before/after unary operators (words on by default, nonwords off by default) "space-unary-ops": [1, { "words": true, "nonwords": false }], // require or disallow spaces before/after unary operators (words on by default, nonwords off by default)
"max-nested-callbacks": 0, // specify the maximum depth callbacks can be nested (off by default) "max-nested-callbacks": 0, // specify the maximum depth callbacks can be nested (off by default)
"one-var": 0, // allow just one var statement per function (off by default) "one-var": 0, // allow just one var statement per function (off by default)

View File

@@ -41,10 +41,10 @@ class DefsExample extends Component{
<Stop offset="100%" stopColor="blue" /> <Stop offset="100%" stopColor="blue" />
</RadialGradient> </RadialGradient>
</Defs> </Defs>
<Use href="url(#path)" x="0" fill="blue" opacity="0.6" /> <Use href="#path" x="0" fill="blue" opacity="0.6" />
<Use href="url(#path)" x="20" y="5" fill="url(#linear)" /> <Use href="#path" x="20" y="5" fill="url(#linear)" />
<Use href="url(#path)" clipPath="url(#clip)" fillOpacity="0.6" stroke="#000" /> <Use href="#path" clipPath="url(#clip)" fillOpacity="0.6" stroke="#000" />
<Use href="url(#path)" x="-10" y="20" fill="red" fill="url(#radial)" /> <Use href="#path" x="-10" y="20" fill="red" fill="url(#radial)" />
</Svg>; </Svg>;
} }
} }
@@ -57,8 +57,12 @@ const icon = <Svg
<G id="path" scale="0.5"> <G id="path" scale="0.5">
<Path fill='red' d="M38.459,1.66A0.884,0.884,0,0,1,39,2.5a0.7,0.7,0,0,1-.3.575L23.235,16.092,27.58,26.1a1.4,1.4,0,0,1,.148.3,1.3,1.3,0,0,1,0,.377,1.266,1.266,0,0,1-2.078.991L15.526,20.6l-7.58,4.35a1.255,1.255,0,0,1-.485,0,1.267,1.267,0,0,1-1.277-1.258q0-.01,0-0.02a1.429,1.429,0,0,1,0-.446C7.243,20.253,8.6,16.369,8.6,16.29L3.433,13.545A0.743,0.743,0,0,1,2.9,12.822a0.822,0.822,0,0,1,.623-0.773l8.164-2.972,3.018-8.5A0.822,0.822,0,0,1,15.427,0a0.752,0.752,0,0,1,.752.555l2.563,6.936S37.65,1.727,37.792,1.685A1.15,1.15,0,0,1,38.459,1.66Z"/> <Path fill='red' d="M38.459,1.66A0.884,0.884,0,0,1,39,2.5a0.7,0.7,0,0,1-.3.575L23.235,16.092,27.58,26.1a1.4,1.4,0,0,1,.148.3,1.3,1.3,0,0,1,0,.377,1.266,1.266,0,0,1-2.078.991L15.526,20.6l-7.58,4.35a1.255,1.255,0,0,1-.485,0,1.267,1.267,0,0,1-1.277-1.258q0-.01,0-0.02a1.429,1.429,0,0,1,0-.446C7.243,20.253,8.6,16.369,8.6,16.29L3.433,13.545A0.743,0.743,0,0,1,2.9,12.822a0.822,0.822,0,0,1,.623-0.773l8.164-2.972,3.018-8.5A0.822,0.822,0,0,1,15.427,0a0.752,0.752,0,0,1,.752.555l2.563,6.936S37.65,1.727,37.792,1.685A1.15,1.15,0,0,1,38.459,1.66Z"/>
</G> </G>
<ClipPath id="clip">
<Circle r="50%" cx="0%" cy="0%" />
</ClipPath>
</Defs> </Defs>
<Use href="url(#path)" fill="#3a8" /> <Use href="#path" fill="#3a8" />
<Use href="#path" fill="red" clipPath="url(#clip)" fillOpacity="0.6" stroke="#000" />
</Svg>; </Svg>;

View File

@@ -97,7 +97,7 @@ class GTransform extends Component{
> >
Text grouped with shapes</Text> Text grouped with shapes</Text>
</G> </G>
<Use href="url(#group)" x="5" y="20" rotate="-50" stroke="red" /> <Use href="#group" x="5" y="20" rotate="-50" stroke="red" opacity="0.5" />
</Svg>; </Svg>;
} }
} }

View File

@@ -15,25 +15,27 @@ class SymbolExample extends Component{
height="150" height="150"
width="110" width="110"
> >
<Symbol id="symbol" viewbox="0 0 150 110" width="100" height="50"> <Symbol id="symbol" viewBox="0 0 150 110" >
<Circle cx="50" cy="50" r="40" strokeWidth="8" stroke="red" fill="red"/> <Circle cx="50" cy="50" r="40" strokeWidth="8" stroke="red" fill="red"/>
<Circle cx="90" cy="60" r="40" strokeWidth="8" stroke="green" fill="white"/> <Circle cx="90" cy="60" r="40" strokeWidth="8" stroke="green" fill="white"/>
</Symbol> </Symbol>
<Use <Use
href="url(#symbol)" href="#symbol"
x="0" x="0"
y="0" y="0"
width="100"
height="50"
/> />
<Use <Use
href="url(#symbol)" href="#symbol"
x="0" x="0"
y="50" y="50"
width="75" width="75"
height="38" height="38"
/> />
<Use <Use
href="url(#symbol)" href="#symbol"
x="0" x="0"
y="100" y="100"
width="50" width="50"
@@ -47,20 +49,20 @@ const icon = <Svg
height="20" height="20"
width="20" width="20"
> >
<Symbol id="symbol" viewbox="0 0 150 110"> <Symbol id="symbol" viewBox="0 0 150 110">
<Circle cx="50" cy="50" r="40" strokeWidth="8" stroke="red" fill="red"/> <Circle cx="50" cy="50" r="40" strokeWidth="8" stroke="red" fill="red"/>
<Circle cx="90" cy="60" r="40" strokeWidth="8" stroke="green" fill="white"/> <Circle cx="90" cy="60" r="40" strokeWidth="8" stroke="green" fill="white"/>
</Symbol> </Symbol>
<Use <Use
href="url(#symbol)" href="#symbol"
x="0" x="0"
y="0" y="0"
width="20" width="20"
height="10" height="10"
/> />
<Use <Use
href="url(#symbol)" href="#symbol"
x="0" x="0"
y="12" y="12"
width="20" width="20"

View File

@@ -27,8 +27,8 @@ class UseExample extends Component{
</G> </G>
</G> </G>
</Defs> </Defs>
<Use href="url(#shape)" x="20" y="0"/> <Use href="#shape" x="20" y="0"/>
<Use href="url(#shape)" x="170"y="0" /> <Use href="#shape" x="170"y="0" />
</Svg>; </Svg>;
} }
} }
@@ -43,9 +43,9 @@ class UseShapes extends Component{
<G id="shape"> <G id="shape">
<Rect x="0" y="0" width="50" height="50" /> <Rect x="0" y="0" width="50" height="50" />
</G> </G>
<Use href="url(#shape)" x="75" y="50" fill="#0f0"/> <Use href="#shape" x="75" y="50" fill="#0f0"/>
<Use href="url(#shape)" x="110" y="0" stroke="#0ff" fill="#8a3" rotation="45" origin="25, 25"/> <Use href="#shape" x="110" y="0" stroke="#0ff" fill="#8a3" rotation="45" origin="25, 25"/>
<Use href="url(#shape)" x="150" y="50" stroke="#0f0" fill="none"/> <Use href="#shape" x="150" y="50" stroke="#0f0" fill="none"/>
</Svg>; </Svg>;
} }
} }
@@ -60,7 +60,7 @@ const icon = <Svg
stroke="#8a3" stroke="#8a3"
id="line" id="line"
/> />
<Use href="url(#line)" x="10" stroke="#3a8" /> <Use href="#line" x="10" stroke="#3a8" />
</Svg>; </Svg>;
const samples = [UseExample, UseShapes]; const samples = [UseExample, UseShapes];

View File

@@ -1,25 +1,36 @@
import React, {Component, PropTypes} from 'react'; import React, {Component, PropTypes} from 'react';
import ViewBox from './ViewBox'; import ViewBox from './ViewBox';
import G from './G'; import G from './G';
import Defs from './Defs';
class SymbolElement extends Component{ class SymbolElement extends Component{
static displayName = 'Symbol'; static displayName = 'Symbol';
static propType = { static propType = {
id: PropTypes.string.isRequired id: PropTypes.string.isRequired,
viewBox: PropTypes.string,
preserveAspectRatio: PropTypes.string
}; };
render() { render() {
let {props} = this; let {props} = this;
return <G id={props.id}> let viewBox = props.viewBox;
<ViewBox if (props.viewbox) {
{...props} viewBox = props.viewbox;
viewbox={props.viewbox} console.warn('Prop `viewbox` is deprecated. please use `viewBox` instead.');
preserveAspectRatio={props.preserveAspectRatio} }
>
{props.children} let content = viewBox ? <ViewBox
</ViewBox> viewBox={viewBox}
</G>; preserveAspectRatio={props.preserveAspectRatio}
>
{props.children}
</ViewBox> : props.children;
return <Defs>
<G id={props.id}>
{content}
</G>
</Defs>;
} }
} }

View File

@@ -1,17 +1,19 @@
import {PropTypes} from 'react'; import {PropTypes} from 'react';
import {pathProps} from '../lib/props'; import {pathProps, numberProp} from '../lib/props';
import {UseAttributes} from '../lib/attributes'; import {UseAttributes} from '../lib/attributes';
import Shape from './Shape'; import Shape from './Shape';
import React from 'react'; import React from 'react';
import patternReg from '../lib/extract/patternReg';
import createReactNativeComponentClass from 'react/lib/createReactNativeComponentClass'; import createReactNativeComponentClass from 'react/lib/createReactNativeComponentClass';
import _ from 'lodash'; import _ from 'lodash';
class Defs extends Shape { const idExpReg = /^#(.+)$/;
class Use extends Shape {
static displayName = 'Use'; static displayName = 'Use';
static propTypes = { static propTypes = {
href: PropTypes.string.isRequired, href: PropTypes.string.isRequired,
width: numberProp, // Just for reusing `Symbol`
height: numberProp, // Just for reusing `Symbol`
...pathProps ...pathProps
}; };
@@ -22,7 +24,7 @@ class Defs extends Shape {
render() { render() {
let {props} = this; let {props} = this;
// 尝试匹配 "url(#pattern)" // 尝试匹配 "url(#pattern)"
let matched = props.href.match(patternReg); let matched = props.href.match(idExpReg);
let href; let href;
if (matched) { if (matched) {
@@ -30,7 +32,7 @@ class Defs extends Shape {
} }
if (!href) { if (!href) {
console.warn('Invalid `href` prop for `Use` element, expected a href like `"url(#id)"`, but got: "' + props.href + '"'); console.warn('Invalid `href` prop for `Use` element, expected a href like `"#id"`, but got: "' + props.href + '"');
} }
let extractedProps = this.extractProps(props, { let extractedProps = this.extractProps(props, {
@@ -44,6 +46,8 @@ class Defs extends Shape {
ref={ele => this.root = ele} ref={ele => this.root = ele}
{...extractedProps} {...extractedProps}
href={href} href={href}
width={props.width}
height={props.height}
>{props.children}</RNSVGUse>; >{props.children}</RNSVGUse>;
} }
} }
@@ -53,5 +57,5 @@ const RNSVGUse = createReactNativeComponentClass({
uiViewClassName: 'RNSVGUse' uiViewClassName: 'RNSVGUse'
}); });
export default Defs; export default Use;

View File

@@ -15,5 +15,6 @@
@interface RNSVGUse : RNSVGRenderable @interface RNSVGUse : RNSVGRenderable
@property (nonatomic, strong) NSString *href; @property (nonatomic, strong) NSString *href;
@property (nonatomic, strong) NSString *width;
@property (nonatomic, strong) NSString *height;
@end @end

View File

@@ -313,10 +313,10 @@
10ABC7381D43982B006CCF6E /* RNSVGVBMOS.h */, 10ABC7381D43982B006CCF6E /* RNSVGVBMOS.h */,
10ABC7371D439779006CCF6E /* RNSVGCGFCRule.h */, 10ABC7371D439779006CCF6E /* RNSVGCGFCRule.h */,
1039D2AE1CE72F27001E90A8 /* RNSVGPercentageConverter.h */, 1039D2AE1CE72F27001E90A8 /* RNSVGPercentageConverter.h */,
1039D2AF1CE72F27001E90A8 /* RNSVGPercentageConverter.m */,
1039D29B1CE72177001E90A8 /* RCTConvert+RNSVG.h */, 1039D29B1CE72177001E90A8 /* RCTConvert+RNSVG.h */,
1039D29C1CE72177001E90A8 /* RCTConvert+RNSVG.m */, 1039D29C1CE72177001E90A8 /* RCTConvert+RNSVG.m */,
1039D29E1CE72177001E90A8 /* RNSVGCGFloatArray.h */, 1039D29E1CE72177001E90A8 /* RNSVGCGFloatArray.h */,
1039D2AF1CE72F27001E90A8 /* RNSVGPercentageConverter.m */,
); );
name = Utils; name = Utils;
sourceTree = "<group>"; sourceTree = "<group>";

View File

@@ -12,7 +12,15 @@
@implementation RNSVGNode @implementation RNSVGNode
{ {
BOOL transparent; BOOL _transparent;
}
- (instancetype)init
{
if (self = [super init]) {
self.opacity = 1;
}
return self;
} }
- (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex - (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex
@@ -57,7 +65,7 @@
} }
[self invalidate]; [self invalidate];
transparent = opacity < 1; _transparent = opacity < 1;
_opacity = opacity; _opacity = opacity;
} }
@@ -69,14 +77,14 @@
- (void)beginTransparencyLayer:(CGContextRef)context - (void)beginTransparencyLayer:(CGContextRef)context
{ {
if (transparent) { if (_transparent) {
CGContextBeginTransparencyLayer(context, NULL); CGContextBeginTransparencyLayer(context, NULL);
} }
} }
- (void)endTransparencyLayer:(CGContextRef)context - (void)endTransparencyLayer:(CGContextRef)context
{ {
if (transparent) { if (_transparent) {
CGContextEndTransparencyLayer(context); CGContextEndTransparencyLayer(context);
} }
} }

View File

@@ -17,5 +17,7 @@
@property (nonatomic, strong) NSString *vbHeight; @property (nonatomic, strong) NSString *vbHeight;
@property (nonatomic, strong) NSString *align; @property (nonatomic, strong) NSString *align;
@property (nonatomic, assign) RNSVGVBMOS meetOrSlice; @property (nonatomic, assign) RNSVGVBMOS meetOrSlice;
@property (nonatomic, strong) NSString *width;
@property (nonatomic, strong) NSString *height;
@end @end

View File

@@ -8,8 +8,12 @@
#import <math.h> #import <math.h>
#import "RNSVGViewBox.h" #import "RNSVGViewBox.h"
#import "RNSVGUse.h"
@implementation RNSVGViewBox @implementation RNSVGViewBox
{
BOOL _fromSymbol;
}
- (void)renderTo:(CGContextRef)context - (void)renderTo:(CGContextRef)context
{ {
@@ -25,8 +29,8 @@
// Let e-x, e-y, e-width, e-height be the position and size of the element respectively. // Let e-x, e-y, e-width, e-height be the position and size of the element respectively.
CGFloat eX = [self getContextX]; CGFloat eX = [self getContextX];
CGFloat eY = [self getContextY]; CGFloat eY = [self getContextY];
CGFloat eWidth = [self getContextWidth]; CGFloat eWidth = self.width ? [self getWidthRelatedValue:self.width] : [self getContextWidth];
CGFloat eHeight = [self getContextHeight]; CGFloat eHeight = self.height ? [self getHeightRelatedValue:self.height] : [self getContextHeight];
// Let align be the align value of preserveAspectRatio, or 'xMidyMid' if preserveAspectRatio is not defined. // Let align be the align value of preserveAspectRatio, or 'xMidyMid' if preserveAspectRatio is not defined.
NSString *align = self.align; NSString *align = self.align;
@@ -91,12 +95,27 @@
translateY -= eHeight / scaleY - vbHeight; translateY -= eHeight / scaleY - vbHeight;
} }
} }
CGAffineTransform transform = CGAffineTransformMakeScale(scaleX, scaleY); CGAffineTransform transform = CGAffineTransformMakeScale(scaleX, scaleY);
transform = CGAffineTransformTranslate(transform, -translateX, -translateY); transform = CGAffineTransformTranslate(transform, -translateX * (_fromSymbol ? scaleX : 1), -translateY * (_fromSymbol ? scaleY : 1));
CGContextConcatCTM(context, transform); CGContextConcatCTM(context, transform);
[super renderTo:context]; [super renderTo:context];
} }
- (void)mergeProperties:(__kindof RNSVGNode *)target mergeList:(NSArray<NSString *> *)mergeList
{
if ([target isKindOfClass:[RNSVGUse class]]) {
RNSVGUse *use = target;
_fromSymbol = YES;
self.width = use.width;
self.height = use.height;
}
}
- (void)resetProperties
{
self.width = self.height = nil;
_fromSymbol = NO;
}
@end @end

View File

@@ -19,5 +19,7 @@ RCT_EXPORT_MODULE()
} }
RCT_EXPORT_VIEW_PROPERTY(href, NSString) RCT_EXPORT_VIEW_PROPERTY(href, NSString)
RCT_EXPORT_VIEW_PROPERTY(width, NSString)
RCT_EXPORT_VIEW_PROPERTY(height, NSString)
@end @end

View File

@@ -92,7 +92,9 @@ const RenderableAttributes = merge({}, NodeAttributes, RenderableOnlyAttributes)
const GroupAttributes = RenderableAttributes; const GroupAttributes = RenderableAttributes;
const UseAttributes = merge({ const UseAttributes = merge({
href: true href: true,
width: true,
height: true
}, RenderableAttributes); }, RenderableAttributes);
const PathAttributes = merge({ const PathAttributes = merge({