mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-19 21:45:10 +00:00
add Use element and add example for it
add Use element and add example for it
This commit is contained in:
@@ -9,6 +9,7 @@ import * as Path from './examples/Path';
|
|||||||
import * as Text from './examples/Text';
|
import * as Text from './examples/Text';
|
||||||
import * as G from './examples/G';
|
import * as G from './examples/G';
|
||||||
import * as Stroking from './examples/Stroking';
|
import * as Stroking from './examples/Stroking';
|
||||||
|
import * as Use from './examples/Use';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Svg,
|
Svg,
|
||||||
@@ -21,5 +22,6 @@ export {
|
|||||||
Path,
|
Path,
|
||||||
Text,
|
Text,
|
||||||
Stroking,
|
Stroking,
|
||||||
G
|
G,
|
||||||
|
Use
|
||||||
};
|
};
|
||||||
|
|||||||
64
Example/examples/Use.js
Normal file
64
Example/examples/Use.js
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import React, {
|
||||||
|
Component
|
||||||
|
} from 'react-native';
|
||||||
|
|
||||||
|
import Svg, {
|
||||||
|
Defs,
|
||||||
|
Use,
|
||||||
|
G,
|
||||||
|
Rect,
|
||||||
|
Circle
|
||||||
|
} from 'react-native-art-svg';
|
||||||
|
|
||||||
|
class UseExample extends Component{
|
||||||
|
static title = 'Reuse svg code';
|
||||||
|
render() {
|
||||||
|
return <Svg
|
||||||
|
height="100"
|
||||||
|
width="300"
|
||||||
|
>
|
||||||
|
<Defs>
|
||||||
|
<G id="shape">
|
||||||
|
<G>
|
||||||
|
<Circle cx="50" cy="50" r="50" />
|
||||||
|
<Rect x="50" y="50" width="50" height="50" />
|
||||||
|
<Circle cx="50" cy="50" r="5" fill="blue" />
|
||||||
|
</G>
|
||||||
|
</G>
|
||||||
|
</Defs>
|
||||||
|
<Use href="#shape" x="20" y="0"/>
|
||||||
|
<Use href="#shape" x="170"y="0" />
|
||||||
|
</Svg>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class UseShapes extends Component{
|
||||||
|
static title = 'Using Shapes Outside of a Defs Element';
|
||||||
|
render() {
|
||||||
|
return <Svg
|
||||||
|
height="110"
|
||||||
|
width="200"
|
||||||
|
>
|
||||||
|
<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="150" y="50" stroke="#0f0" fill="none"/>
|
||||||
|
</Svg>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const icon = <Svg
|
||||||
|
height="20"
|
||||||
|
width="20"
|
||||||
|
>
|
||||||
|
|
||||||
|
</Svg>;
|
||||||
|
|
||||||
|
const samples = [UseExample, UseShapes];
|
||||||
|
|
||||||
|
export {
|
||||||
|
icon,
|
||||||
|
samples
|
||||||
|
}
|
||||||
@@ -107,7 +107,7 @@ const styles = StyleSheet.create({
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const names = ['Svg', 'Stroking', 'Path', 'Line', 'Rect', 'Polygon', 'Polyline', 'Circle', 'Ellipse', 'G', 'Text'];
|
const names = ['Svg', 'Stroking', 'Path', 'Line', 'Rect', 'Polygon', 'Polyline', 'Circle', 'Ellipse', 'G', 'Text', 'Use'];
|
||||||
|
|
||||||
class ArtSvgExample extends Component {
|
class ArtSvgExample extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|||||||
15
README.md
15
README.md
@@ -1,6 +1,7 @@
|
|||||||
### react-native-art-svg
|
### react-native-art-svg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
1. fill-rule:evenodd
|
1. fill-rule:evenodd
|
||||||
2. gradients
|
2. gradients
|
||||||
@@ -9,20 +10,14 @@ TODO:
|
|||||||
|
|
||||||
elements:
|
elements:
|
||||||
1.defs
|
1.defs
|
||||||
|
|
||||||
2.tref !
|
2.tref !
|
||||||
3.tspan !
|
3.tspan !
|
||||||
|
|
||||||
4.clipPath (wait for official todo)
|
4.clipPath (wait for official todo)
|
||||||
|
5.glyph ? missing-glyph?
|
||||||
6.glyph ? missing-glyph?
|
6.linearGradient
|
||||||
|
7.radialGradient
|
||||||
7.linearGradient
|
|
||||||
|
|
||||||
8.marker?
|
8.marker?
|
||||||
9.pattern
|
9.pattern
|
||||||
10.radialGradient
|
10.textPath
|
||||||
11.stop
|
11.stop
|
||||||
12.symbol
|
12.symbol
|
||||||
13.use
|
|
||||||
14.textPath
|
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ class Circle extends Component{
|
|||||||
{...this.props}
|
{...this.props}
|
||||||
{...strokeFilter(this.props)}
|
{...strokeFilter(this.props)}
|
||||||
r={null}
|
r={null}
|
||||||
rx={this.props.r}
|
rx={+this.props.r}
|
||||||
ry={this.props.r}
|
ry={+this.props.r}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ let {
|
|||||||
Group
|
Group
|
||||||
} = ART;
|
} = ART;
|
||||||
|
|
||||||
|
import Defs from './Defs';
|
||||||
|
|
||||||
const transformProps = {
|
const transformProps = {
|
||||||
scale: null,
|
scale: null,
|
||||||
scaleX: null,
|
scaleX: null,
|
||||||
@@ -29,19 +31,23 @@ class G extends Component{
|
|||||||
constructor() {
|
constructor() {
|
||||||
super(...arguments);
|
super(...arguments);
|
||||||
this.children = Children.map(this.props.children, child => cloneElement(child, {
|
this.children = Children.map(this.props.children, child => cloneElement(child, {
|
||||||
id: null,
|
|
||||||
...this.props,
|
...this.props,
|
||||||
...transformProps,
|
...transformProps,
|
||||||
children: child.children,
|
...child.props,
|
||||||
...child.props
|
id: null
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <Group
|
let element = <Group
|
||||||
{...this.props}
|
{...this.props}
|
||||||
{...transformFilter(this.props)}
|
{...transformFilter(this.props)}
|
||||||
|
id={null}
|
||||||
>{this.children}</Group>;
|
>{this.children}</Group>;
|
||||||
|
if (this.props.id) {
|
||||||
|
Defs.set(this.props.id + ':' + this.props.svgId, <G {...this.props} id={null} />);
|
||||||
|
}
|
||||||
|
return element;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import React, {
|
import React, {
|
||||||
ART,
|
ART,
|
||||||
Component,
|
Component,
|
||||||
PropTypes
|
PropTypes,
|
||||||
|
cloneElement
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
Shape
|
Shape
|
||||||
} = ART;
|
} = ART;
|
||||||
|
import Defs from './Defs';
|
||||||
|
|
||||||
import fillFilter from '../lib/fillFilter';
|
import fillFilter from '../lib/fillFilter';
|
||||||
import strokeFilter from '../lib/strokeFilter';
|
import strokeFilter from '../lib/strokeFilter';
|
||||||
@@ -25,12 +27,16 @@ class Path extends Component{
|
|||||||
};
|
};
|
||||||
render() {
|
render() {
|
||||||
let {props} = this;
|
let {props} = this;
|
||||||
|
let element = <Shape
|
||||||
return <Shape
|
|
||||||
{...props}
|
{...props}
|
||||||
{...strokeFilter(props)}
|
{...strokeFilter(props)}
|
||||||
fill={fillFilter(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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import React, {
|
|||||||
|
|
||||||
import fillFilter from '../lib/fillFilter';
|
import fillFilter from '../lib/fillFilter';
|
||||||
import strokeFilter from '../lib/strokeFilter';
|
import strokeFilter from '../lib/strokeFilter';
|
||||||
|
import transformFilter from '../lib/transformFilter';
|
||||||
import Path from './Path';
|
import Path from './Path';
|
||||||
|
|
||||||
let propType = PropTypes.oneOfType([PropTypes.string, PropTypes.number]);
|
let propType = PropTypes.oneOfType([PropTypes.string, PropTypes.number]);
|
||||||
@@ -82,17 +83,17 @@ class Rect extends Component{
|
|||||||
h ${-width}
|
h ${-width}
|
||||||
Z
|
Z
|
||||||
`;
|
`;
|
||||||
|
|
||||||
return <Path
|
return <Path
|
||||||
{...props}
|
{...props}
|
||||||
x={rx ? +rx: null}
|
|
||||||
y={null}
|
|
||||||
rx={null}
|
rx={null}
|
||||||
ry={null}
|
ry={null}
|
||||||
width={null}
|
width={null}
|
||||||
height={null}
|
height={null}
|
||||||
{...strokeFilter(props)}
|
{...strokeFilter(props)}
|
||||||
fill={fillFilter(props)}
|
fill={fillFilter(props)}
|
||||||
|
{...transformFilter(props)}
|
||||||
|
x={null}
|
||||||
|
y={null}
|
||||||
d={d}
|
d={d}
|
||||||
/>;
|
/>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import React, {
|
import React, {
|
||||||
ART,
|
ART,
|
||||||
Component,
|
Component,
|
||||||
PropTypes
|
PropTypes,
|
||||||
|
Children,
|
||||||
|
cloneElement
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
@@ -71,6 +73,8 @@ function extractViewbox({viewbox, width, height, preserveAspectRatio}) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let id = 0;
|
||||||
|
|
||||||
class Svg extends Component{
|
class Svg extends Component{
|
||||||
static displayName = 'Svg';
|
static displayName = 'Svg';
|
||||||
static propType = {
|
static propType = {
|
||||||
@@ -82,6 +86,20 @@ class Svg extends Component{
|
|||||||
preserveAspectRatio: PropTypes.string // preserveAspectRatio only supports 'none' for now
|
preserveAspectRatio: PropTypes.string // preserveAspectRatio only supports 'none' for now
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super(...arguments);
|
||||||
|
id++;
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
getChildren = () => {
|
||||||
|
return Children.map(this.props.children, child => {
|
||||||
|
return cloneElement(child, {
|
||||||
|
svgId: this.id
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let opacity = +this.props.opacity;
|
let opacity = +this.props.opacity;
|
||||||
let viewbox = extractViewbox(this.props);
|
let viewbox = extractViewbox(this.props);
|
||||||
@@ -104,7 +122,7 @@ class Svg extends Component{
|
|||||||
scaleX={scaleX}
|
scaleX={scaleX}
|
||||||
scaleY={scaleY}
|
scaleY={scaleY}
|
||||||
>
|
>
|
||||||
{this.props.children}
|
{this.getChildren()}
|
||||||
</Group>}
|
</Group>}
|
||||||
</Surface>;
|
</Surface>;
|
||||||
}
|
}
|
||||||
@@ -118,7 +136,7 @@ class Svg extends Component{
|
|||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{this.props.children}
|
{this.getChildren()}
|
||||||
</Surface>;
|
</Surface>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import React, {
|
|||||||
let {
|
let {
|
||||||
Text:ARTText
|
Text:ARTText
|
||||||
} = ART;
|
} = ART;
|
||||||
|
import Defs from './Defs';
|
||||||
|
|
||||||
import fillFilter from '../lib/fillFilter';
|
import fillFilter from '../lib/fillFilter';
|
||||||
import strokeFilter from '../lib/strokeFilter';
|
import strokeFilter from '../lib/strokeFilter';
|
||||||
@@ -33,7 +34,7 @@ class Text extends Component{
|
|||||||
y = props.dy ? +props.y + (+props.dy) : +props.y;
|
y = props.dy ? +props.y + (+props.dy) : +props.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <ARTText
|
let element = <ARTText
|
||||||
{...props}
|
{...props}
|
||||||
{...transformFilter(props)}
|
{...transformFilter(props)}
|
||||||
{...strokeFilter(props)}
|
{...strokeFilter(props)}
|
||||||
@@ -47,7 +48,12 @@ class Text extends Component{
|
|||||||
alignment={props.textAnchor || props.alignment}
|
alignment={props.textAnchor || props.alignment}
|
||||||
x={x}
|
x={x}
|
||||||
y={y}
|
y={y}
|
||||||
|
id={null}
|
||||||
/>;
|
/>;
|
||||||
|
if (this.props.id) {
|
||||||
|
Defs.set(this.props.id + ':' + this.props.svgId, <Text {...this.props} id={null} />);
|
||||||
|
}
|
||||||
|
return element;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
37
elements/Use.js
Normal file
37
elements/Use.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import React, {
|
||||||
|
Component,
|
||||||
|
PropTypes,
|
||||||
|
ART,
|
||||||
|
cloneElement
|
||||||
|
} 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 = {
|
||||||
|
href: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
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 />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Use;
|
||||||
@@ -8,6 +8,8 @@ export default function (props) {
|
|||||||
rotation: props.rotation || props.rotate || 0,
|
rotation: props.rotation || props.rotate || 0,
|
||||||
scale: props.scale || 1,
|
scale: props.scale || 1,
|
||||||
originX,
|
originX,
|
||||||
originY
|
originY,
|
||||||
|
x: +props.x || 0,
|
||||||
|
y: +props.y || 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user