Refactor reuse elements

Refactor reuse elements
This commit is contained in:
Horcrux
2016-01-25 11:39:31 +08:00
parent 5f3c2e8e39
commit e001285cbe
16 changed files with 171 additions and 101 deletions

View File

@@ -47,13 +47,35 @@ class TextRotate extends Component{
x="126"
y="24"
fill="#f60"
rotate="16"
rotate="78"
scale="1.36"
origin="20, 0"
>I love SVG</Text>
</Svg>;
}
}
class TextStroke extends Component{
static title = 'Stroke the text';
render() {
return <Svg
height="60"
width="200"
>
<Text
fill="none"
stroke="purple"
fontSize="20"
fontWeight="bold"
x="100"
y="20"
alignment="center"
>STROKED TEXT</Text>
</Svg>;
}
}
// TODO: wait for official done
class TextPath extends Component{
static title = 'Transform the text';
@@ -90,7 +112,7 @@ const icon = <Svg
></Text>
</Svg>;
const samples = [TextExample, TextRotate];
const samples = [TextExample, TextRotate, TextStroke];
export {
icon,

View File

@@ -7,7 +7,8 @@ import Svg, {
Use,
G,
Rect,
Circle
Circle,
Polyline
} from 'react-native-art-svg';
class UseExample extends Component{
@@ -42,8 +43,8 @@ class UseShapes extends Component{
<G id="shape">
<Rect x="0" y="0" width="50" height="50" />
</G>
<Use href="#shape" x="75" y="50" fill="#0f0"/>
<Use href="#shape" x="110" y="0" stroke="#0ff" fill="#8a3" rotation="45" origin="25, 25"/>
<Use href="#shape" x="150" y="50" stroke="#0f0" fill="none"/>
</Svg>;
};
@@ -53,7 +54,13 @@ const icon = <Svg
height="20"
width="20"
>
<Polyline
points="5,0 2,2 2,4 6,6 3,8 6,10 7,12 5,14 8,16 9,18"
fill="none"
stroke="#8a3"
id="line"
/>
<Use href="#line" x="10" stroke="#3a8" />
</Svg>;
const samples = [UseExample, UseShapes];

View File

@@ -23,9 +23,7 @@ import {
Line
} from 'react-native-art-svg';
import * as examples from './examples';
import _ from 'lodash';
import Modal from 'react-native-root-modal';
const hairline = 1 / PixelRatio.get();
const styles = StyleSheet.create({
@@ -106,7 +104,6 @@ const styles = StyleSheet.create({
}
});
const names = ['Svg', 'Stroking', 'Path', 'Line', 'Rect', 'Polygon', 'Polyline', 'Circle', 'Ellipse', 'G', 'Text', 'Use'];
class ArtSvgExample extends Component {

View File

@@ -6,6 +6,8 @@
"start": "react-native start"
},
"dependencies": {
"react-native": "^0.18.1"
"react-native": "^0 .18.1",
"react-native-art-svg": "^1.0.1",
"react-native-root-modal": "^1.0.2"
}
}

View File

@@ -14,13 +14,12 @@ class Circle extends Component{
};
static defaultProps = {
cx: 0,
ct: 0
cy: 0
};
render() {
return <Ellipse
{...this.props}
{...strokeFilter(this.props)}
r={null}
rx={+this.props.r}
ry={+this.props.r}

View File

@@ -1,45 +1,96 @@
import React, {
Children,
cloneElement,
Component,
ART
ART,
cloneElement,
PropTypes
} from 'react-native';
let {Group} = ART;
let map = {};
let onlyChild = Children.only;
class DefsItem extends Component{
static displayName = 'DefsItem';
static propType = {
visible: PropTypes.bool
};
static defaultProps = {
visible: false
};
constructor() {
super(...arguments);
this.id = this.props.id + ':' + this.props.svgId;
map[this.id] = cloneElement(onlyChild(this.props.children), {
id: null
});
}
componentWillReceiveProps = nextProps => {
let id = nextProps.id + ':' + nextProps.svgId;
if (id !== this.id) {
delete map[this.id];
}
map[id] = cloneElement(onlyChild(nextProps.children), {
id: null
});
};
componentWillUnmount = () => {
delete map[this.id];
};
render() {
return this.props.visible ? onlyChild(this.props.children) : <Group />;
}
}
let idReg = /^#(.+)/;
class DefsUse extends Component{
static displayName = 'DefsUse';
static propType = {
href: PropTypes.string
};
render() {
let href = this.props.href;
if (href) {
let matched = href.match(idReg);
if (matched) {
let template = map[matched[1] + ':' + this.props.svgId];
if (template) {
let props = {
...this.props,
href: null
};
return cloneElement(template, props);
}
}
}
console.warn(`Invalid href: '${href}' for Use element.\n Please check if '${href}' if defined`);
return <Group />;
}
}
// TODO: more details should be handled(different Svg namespace、(remove, add, update) Defs children)
class Defs extends Component{
static displayName = 'Defs';
static get = uid => {
return map[uid];
};
static Item = DefsItem;
static Use = DefsUse;
static set = (uid, element) => {
map[uid] = element;
};
componentWillMount = () => {
this.getDefines(this.props.children);
};
componentWillReceiveProps = nextProps => {
this.getDefines(nextProps);
};
getDefines = children => {
Children.map(children, child => {
let {props: {id}} = child;
if (id) {
console.log(id + ':' + this.props.svgId);
map[id + ':' + this.props.svgId] = cloneElement(child, {
id: null
});
getChildren = () => {
return Children.map(this.props.children, child => {
if (child.props.id) {
return <DefsItem {...child.props} svgId={this.props.svgId}>{child}</DefsItem>;
}
});
};
render() {
return <Group />;
return <Group>
{this.getChildren()}
</Group>;
}
}

View File

@@ -5,10 +5,7 @@ import React, {
} from 'react-native';
import fillFilter from '../lib/fillFilter';
import strokeFilter from '../lib/strokeFilter';
let {
Shape
} = ART;
import Path from './Path';
let propType = PropTypes.oneOfType([PropTypes.string, PropTypes.number]);
class Ellipse extends Component{
@@ -28,10 +25,8 @@ class Ellipse extends Component{
a ${rx}, ${ry} 0 1, 0 ${-rx * 2}, 0
Z
`;
return <Shape
return <Path
{...props}
fill={fillFilter(props)}
{...strokeFilter(props)}
strokeCap={null}
strokeJoin={null}
cx={null}

View File

@@ -4,11 +4,9 @@ import React, {
Children,
cloneElement
} from 'react-native';
let {
Group
} = ART;
import Defs from './Defs';
const transformProps = {
@@ -28,9 +26,8 @@ import transformFilter from '../lib/transformFilter';
class G extends Component{
static displayName = 'G';
constructor() {
super(...arguments);
this.children = Children.map(this.props.children, child => cloneElement(child, {
getChildren = () => {
return Children.map(this.props.children, child => cloneElement(child, {
...this.props,
...transformProps,
...child.props,
@@ -39,15 +36,21 @@ class G extends Component{
};
render() {
let element = <Group
if (this.props.id) {
return <Defs.Item
id={this.props.id}
svgId={this.props.svgId}
visible={true}
>
<G {...this.props} id={null} />
</Defs.Item>;
} else {
return <Group
{...this.props}
{...transformFilter(this.props)}
id={null}
>{this.children}</Group>;
if (this.props.id) {
Defs.set(this.props.id + ':' + this.props.svgId, <G {...this.props} id={null} />);
>{this.getChildren()}</Group>;
}
return element;
}
}

View File

@@ -31,7 +31,6 @@ class Line extends Component{
x2={null}
y2={null}
fill={null}
{...strokeFilter(props)}
d={d}
/>;
}

View File

@@ -4,7 +4,6 @@ import React, {
PropTypes,
cloneElement
} from 'react-native';
let {
Shape
} = ART;
@@ -12,6 +11,7 @@ import Defs from './Defs';
import fillFilter from '../lib/fillFilter';
import strokeFilter from '../lib/strokeFilter';
import transformFilter from '../lib/transformFilter';
let propType = PropTypes.oneOfType([PropTypes.string, PropTypes.number]);
class Path extends Component{
static displayName = 'Path';
@@ -27,16 +27,22 @@ class Path extends Component{
};
render() {
let {props} = this;
let element = <Shape
if (props.id) {
return <Defs.Item
id={props.id}
svgId={props.svgId}
visible={true}
>
<Path {...props} id={null} />
</Defs.Item>;
}
return <Shape
{...props}
{...strokeFilter(props)}
{...transformFilter(props)}
fill={fillFilter(props)}
id={null}
/>;
if (this.props.id) {
Defs.set(this.props.id + ':' + this.props.svgId, <Path {...this.props} id={null} />);
}
return element;
}
}

View File

@@ -17,8 +17,6 @@ class Polygon extends Component{
let d = 'M' + props.points.trim().replace(/\s+/g, 'L') + 'z';
return <Path
{...props}
{...strokeFilter(props)}
fill={fillFilter(props)}
points={null}
d={d}
/>;

View File

@@ -8,6 +8,7 @@ import Path from './Path';
import strokeFilter from '../lib/strokeFilter';
import fillFilter from '../lib/fillFilter';
import transformFilter from '../lib/transformFilter';
class Polyline extends Component{
static displayName = 'Polyline';
static propTypes = {
@@ -22,8 +23,6 @@ class Polyline extends Component{
let d = 'M' + props.points.trim().replace(/\s+/g, 'L');
return <Path
{...props}
{...strokeFilter(props)}
fill={fillFilter(props)}
points={null}
d={d}
/>;

View File

@@ -89,10 +89,7 @@ class Rect extends Component{
ry={null}
width={null}
height={null}
{...strokeFilter(props)}
fill={fillFilter(props)}
{...transformFilter(props)}
x={null}
x={rx || null}
y={null}
d={d}
/>;

View File

@@ -3,7 +3,6 @@ import React, {
Component,
PropTypes
} from 'react-native';
let {
Text:ARTText
} = ART;
@@ -34,7 +33,16 @@ class Text extends Component{
y = props.dy ? +props.y + (+props.dy) : +props.y;
}
let element = <ARTText
if (this.props.id) {
return <Defs.Item
id={this.props.id}
svgId={this.props.svgId}
visible={true}
>
<Text {...this.props} id={null} />
</Defs.Item>;
}
return <ARTText
{...props}
{...transformFilter(props)}
{...strokeFilter(props)}
@@ -50,10 +58,6 @@ class Text extends Component{
y={y}
id={null}
/>;
if (this.props.id) {
Defs.set(this.props.id + ':' + this.props.svgId, <Text {...this.props} id={null} />);
}
return element;
}
}

View File

@@ -1,13 +1,10 @@
import React, {
Component,
PropTypes,
ART,
cloneElement
ART
} from 'react-native';
let {Group} = ART;
import Defs from './Defs';
import transformFilter from '../lib/transformFilter';
let idReg = /^#(.+)/;
class Use extends Component{
static displayName = 'Use';
static propType = {
@@ -15,22 +12,7 @@ class Use extends Component{
};
render() {
let href = this.props.href;
if (href) {
let matched = href.match(idReg);
if (matched) {
let template = Defs.get(matched[1] + ':' + this.props.svgId);
if (template) {
let props = {
...this.props,
href: null
};
return cloneElement(template, props);
}
}
}
return <Group />;
return <Defs.Use {...this.props} />;
}
}

View File

@@ -7,23 +7,32 @@ import Circle from './elements/Circle';
import Ellipse from './elements/Ellipse';
import Polygon from './elements/Polygon';
import Polyline from './elements/Polyline';
import Line from './elements/Line';
import Svg from './elements/Svg';
import Path from './elements/Path';
import G from './elements/G';
import Text from './elements/Text';
import Use from './elements/Use';
import Defs from './elements/Defs';
let {
Group
} = ART;
export {
Svg,
Circle,
Ellipse,
Group,
G,
Text,
Path,
Polygon,
Polyline,
Rect
Line,
Rect,
Use,
Defs
};
export default Svg;