mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-20 14:05:09 +00:00
Add Text
Add Text
This commit is contained in:
@@ -6,6 +6,7 @@ import * as Line from './examples/Line';
|
|||||||
import * as Polygon from './examples/Polygon';
|
import * as Polygon from './examples/Polygon';
|
||||||
import * as Polyline from './examples/Polyline';
|
import * as Polyline from './examples/Polyline';
|
||||||
import * as Path from './examples/Path';
|
import * as Path from './examples/Path';
|
||||||
|
import * as Text from './examples/Text';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Svg,
|
Svg,
|
||||||
@@ -15,5 +16,6 @@ export {
|
|||||||
Line,
|
Line,
|
||||||
Polygon,
|
Polygon,
|
||||||
Polyline,
|
Polyline,
|
||||||
Path
|
Path,
|
||||||
|
Text
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -83,15 +83,15 @@ class BezierCurve extends Component{
|
|||||||
</G>
|
</G>
|
||||||
<G
|
<G
|
||||||
fontSize="30"
|
fontSize="30"
|
||||||
fontFamily="sans-serif"
|
|
||||||
fill="black"
|
fill="black"
|
||||||
stroke="none"
|
stroke="none"
|
||||||
textAnchor="middle"
|
textAnchor="middle"
|
||||||
>
|
>
|
||||||
<Text x="100" y="350" dx="-30">A</Text>
|
<Text x="100" y="350" dx="-30">A</Text>
|
||||||
<Text x="250" y="50" dy="-10">B</Text>
|
<Text x="250" y="50" dy="-50">B</Text>
|
||||||
<Text x="400" y="350" dx="30">C</Text>
|
<Text x="400" y="350" dx="10">C</Text>
|
||||||
</G>
|
</G>
|
||||||
|
|
||||||
</G>
|
</G>
|
||||||
</Svg>;
|
</Svg>;
|
||||||
}
|
}
|
||||||
|
|||||||
47
Example/examples/Stroking.js
Normal file
47
Example/examples/Stroking.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import React, {
|
||||||
|
Component
|
||||||
|
} from 'react-native';
|
||||||
|
|
||||||
|
import Svg, {
|
||||||
|
Line
|
||||||
|
} from 'react-native-art-svg';
|
||||||
|
|
||||||
|
class LineExample extends Component{
|
||||||
|
static title = 'Line';
|
||||||
|
render() {
|
||||||
|
return <Svg
|
||||||
|
height="100"
|
||||||
|
width="100"
|
||||||
|
>
|
||||||
|
<Line
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="100"
|
||||||
|
y2="100"
|
||||||
|
stroke="red"
|
||||||
|
strokeWidth="2"
|
||||||
|
/>
|
||||||
|
</Svg>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const icon = <Svg
|
||||||
|
height="20"
|
||||||
|
width="20"
|
||||||
|
>
|
||||||
|
<Line
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="20"
|
||||||
|
y2="20"
|
||||||
|
stroke="red"
|
||||||
|
strokeWidth="1"
|
||||||
|
/>
|
||||||
|
</Svg>;
|
||||||
|
|
||||||
|
const samples = [LineExample];
|
||||||
|
|
||||||
|
export {
|
||||||
|
icon,
|
||||||
|
samples
|
||||||
|
}
|
||||||
@@ -35,6 +35,35 @@ class SvgExample extends Component{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SvgViewbox extends Component{
|
||||||
|
static title = 'SVG with `viewbox` prop';
|
||||||
|
render() {
|
||||||
|
return <Svg
|
||||||
|
height="100"
|
||||||
|
width="100"
|
||||||
|
viewbox="30 30 70 70"
|
||||||
|
>
|
||||||
|
<Circle
|
||||||
|
cx="50"
|
||||||
|
cy="50"
|
||||||
|
r="45"
|
||||||
|
stroke="blue"
|
||||||
|
strokeWidth="2.5"
|
||||||
|
fill="green"
|
||||||
|
/>
|
||||||
|
<Rect
|
||||||
|
x="15"
|
||||||
|
y="15"
|
||||||
|
width="70"
|
||||||
|
height="70"
|
||||||
|
stroke="red"
|
||||||
|
strokeWidth="2"
|
||||||
|
fill="yellow"
|
||||||
|
/>
|
||||||
|
</Svg>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class SvgOpacity extends Component{
|
class SvgOpacity extends Component{
|
||||||
static title = 'SVG with `opacity` prop';
|
static title = 'SVG with `opacity` prop';
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
96
Example/examples/Text.js
Normal file
96
Example/examples/Text.js
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import React, {
|
||||||
|
Component
|
||||||
|
} from 'react-native';
|
||||||
|
|
||||||
|
import Svg, {
|
||||||
|
Text
|
||||||
|
} from 'react-native-art-svg';
|
||||||
|
|
||||||
|
class TextExample extends Component{
|
||||||
|
static title = 'Text';
|
||||||
|
render() {
|
||||||
|
return <Svg
|
||||||
|
height="30"
|
||||||
|
width="100"
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
x="50"
|
||||||
|
y="9"
|
||||||
|
fill="red"
|
||||||
|
textAnchor="center"
|
||||||
|
>I love SVG!</Text>
|
||||||
|
</Svg>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TextRotate extends Component{
|
||||||
|
static title = 'Transform the text';
|
||||||
|
render() {
|
||||||
|
return <Svg
|
||||||
|
height="60"
|
||||||
|
width="200"
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
x="0"
|
||||||
|
y="15"
|
||||||
|
fill="red"
|
||||||
|
rotate="30"
|
||||||
|
origin="20,40"
|
||||||
|
>I love SVG</Text>
|
||||||
|
<Text
|
||||||
|
x="95"
|
||||||
|
y="47"
|
||||||
|
fill="blue"
|
||||||
|
rotate="-67"
|
||||||
|
>I love SVG</Text>
|
||||||
|
<Text
|
||||||
|
x="126"
|
||||||
|
y="24"
|
||||||
|
fill="#f60"
|
||||||
|
rotate="16"
|
||||||
|
scale="1.36"
|
||||||
|
>I love SVG</Text>
|
||||||
|
</Svg>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: wait for official done
|
||||||
|
class TextPath extends Component{
|
||||||
|
static title = 'Transform the text';
|
||||||
|
render() {
|
||||||
|
return <Svg
|
||||||
|
height="60"
|
||||||
|
width="200"
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
fill="red"
|
||||||
|
path={`
|
||||||
|
M 10 20
|
||||||
|
C 20 10 30 0 40 10
|
||||||
|
C 50 20 60 30 70 20
|
||||||
|
C 80 10 90 10 90 10
|
||||||
|
`}
|
||||||
|
>We go up, then we go down, then up again</Text>
|
||||||
|
</Svg>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const icon = <Svg
|
||||||
|
height="20"
|
||||||
|
width="20"
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
x="10"
|
||||||
|
y="2"
|
||||||
|
fontSize="14"
|
||||||
|
fontWeight="bold"
|
||||||
|
textAnchor="center"
|
||||||
|
>字</Text>
|
||||||
|
</Svg>;
|
||||||
|
|
||||||
|
const samples = [TextExample, TextRotate];
|
||||||
|
|
||||||
|
export {
|
||||||
|
icon,
|
||||||
|
samples
|
||||||
|
}
|
||||||
@@ -107,7 +107,7 @@ const styles = StyleSheet.create({
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const names = ['Svg', 'Circle', 'Ellipse', 'G', 'Path', 'Polygon', 'Polyline', 'Line', 'Rect'];
|
const names = ['Svg', 'Circle', 'Ellipse', 'G', 'Text', 'Path', 'Polygon', 'Polyline', 'Line', 'Rect'];
|
||||||
|
|
||||||
class ArtSvgExample extends Component {
|
class ArtSvgExample extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -157,7 +157,7 @@ class ArtSvgExample extends Component {
|
|||||||
Animated.timing(this.state.scale, {
|
Animated.timing(this.state.scale, {
|
||||||
toValue: 0,
|
toValue: 0,
|
||||||
easing: Easing.in(Easing.back(2))
|
easing: Easing.in(Easing.back(2))
|
||||||
}).start(() => this.setState({
|
}).start(({finished}) => finished && this.setState({
|
||||||
modal: false,
|
modal: false,
|
||||||
content: null
|
content: null
|
||||||
}));
|
}));
|
||||||
|
|||||||
28
README.md
28
README.md
@@ -1,9 +1,35 @@
|
|||||||
### react-native-art-svg
|
### react-native-art-svg
|
||||||
|
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
1. fill-rule:evenodd
|
1. fill-rule:evenodd
|
||||||
2. gradients
|
2. gradients
|
||||||
3. text
|
3. text
|
||||||
4. other elements
|
4. other elements
|
||||||
5. animations https://github.com/maxwellito/vivus
|
5. animations https://github.com/maxwellito/vivus
|
||||||
|
|
||||||
|
|
||||||
|
elements:
|
||||||
|
1.defs
|
||||||
|
|
||||||
|
|
||||||
|
2.tref !
|
||||||
|
3.tspan !
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
4.clipPath (wait for official todo)
|
||||||
|
5.svg:viewBox (wait for official todo)
|
||||||
|
|
||||||
|
|
||||||
|
6.glyph ? missing-glyph?
|
||||||
|
|
||||||
|
7.linearGradient
|
||||||
|
|
||||||
|
8.marker?
|
||||||
|
9.pattern
|
||||||
|
10.radialGradient
|
||||||
|
11.stop
|
||||||
|
12.symbol
|
||||||
|
13.use
|
||||||
|
14.textPath
|
||||||
|
|||||||
@@ -1,17 +1,52 @@
|
|||||||
import React, {
|
import React, {
|
||||||
ART,
|
ART,
|
||||||
Component
|
Component,
|
||||||
|
PropTypes
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
let {
|
let {
|
||||||
Surface
|
Surface,
|
||||||
|
ClippingRectangle
|
||||||
} = ART;
|
} = ART;
|
||||||
|
|
||||||
|
function extractViewbox({viewbox, width, height}) {
|
||||||
|
let x = 0;
|
||||||
|
let y = 0;
|
||||||
|
if (typeof viewbox === 'string') {
|
||||||
|
let parts = viewbox.trim().split(/\s+/);
|
||||||
|
if (parts.length === 4) {
|
||||||
|
return {
|
||||||
|
x: parts[0],
|
||||||
|
y: parts[1],
|
||||||
|
width: parts[2],
|
||||||
|
height: parts[3]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
class Svg extends Component{
|
class Svg extends Component{
|
||||||
static displayName = 'Svg';
|
static displayName = 'Svg';
|
||||||
|
static propType = {
|
||||||
|
opacity: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
|
viewbox: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let opacity = +this.props.opacity;
|
let opacity = +this.props.opacity;
|
||||||
|
let {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
} = extractViewbox(this.props);
|
||||||
return <Surface
|
return <Surface
|
||||||
{...this.props}
|
{...this.props}
|
||||||
style={[
|
style={[
|
||||||
@@ -20,7 +55,16 @@ class Svg extends Component{
|
|||||||
opacity: opacity
|
opacity: opacity
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
/>;
|
>
|
||||||
|
<ClippingRectangle
|
||||||
|
x={x}
|
||||||
|
y={y}
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
>
|
||||||
|
{this.props.children}
|
||||||
|
</ClippingRectangle>
|
||||||
|
</Surface>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,13 @@ import React, {
|
|||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
Text:ARTText,
|
Text:ARTText
|
||||||
Shape
|
|
||||||
} = ART;
|
} = ART;
|
||||||
|
|
||||||
import fillFilter from '../lib/fillFilter';
|
import fillFilter from '../lib/fillFilter';
|
||||||
import strokeFilter from '../lib/strokeFilter';
|
import strokeFilter from '../lib/strokeFilter';
|
||||||
|
|
||||||
|
const fontFamily = '"Helvetica Neue", "Helvetica", Arial';
|
||||||
class Text extends Component{
|
class Text extends Component{
|
||||||
static displayName = 'Text';
|
static displayName = 'Text';
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@@ -21,15 +22,40 @@ class Text extends Component{
|
|||||||
};
|
};
|
||||||
render() {
|
render() {
|
||||||
let {props} = this;
|
let {props} = this;
|
||||||
return <Shape d="M0, 0 L0, 0Z" />;
|
|
||||||
|
|
||||||
return <ARTText
|
let x = 0;
|
||||||
|
if (props.x) {
|
||||||
|
x = props.dx ? +props.x + (+props.dx) : +props.x;
|
||||||
|
}
|
||||||
|
let y = 0;
|
||||||
|
if (props.y) {
|
||||||
|
y = props.dy ? +props.y + (+props.dy) : +props.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
let coords = props.origin ? props.origin.split(',') : [];
|
||||||
|
|
||||||
|
let originX = coords.length === 2 ? coords[0] : props.originX;
|
||||||
|
let originY = coords.length === 2 ? coords[1] :props.originY;
|
||||||
|
|
||||||
|
return <ARTText
|
||||||
{...props}
|
{...props}
|
||||||
|
font={{
|
||||||
|
fontSize: props.fontSize || 12,
|
||||||
|
fontFamily: props.fontFamily || fontFamily,
|
||||||
|
fontWeight: props.fontWeight,
|
||||||
|
fontStyle: props.fontStyle
|
||||||
|
}}
|
||||||
|
rotation={props.rotation || props.rotate || 0}
|
||||||
|
scale={props.scale || 1}
|
||||||
|
originX={originX}
|
||||||
|
originY={originY}
|
||||||
strokeCap={props.strokeLinecap || props.strokeCap || 'square'}
|
strokeCap={props.strokeLinecap || props.strokeCap || 'square'}
|
||||||
strokeJoin={props.strokeLinejoin || props.strokeJoin || 'miter'}
|
strokeJoin={props.strokeLinejoin || props.strokeJoin || 'miter'}
|
||||||
alignment={props.textAnchor || props.alignment}
|
alignment={props.textAnchor || props.alignment}
|
||||||
fill={fillFilter(props)}
|
fill={fillFilter(props)}
|
||||||
stroke={strokeFilter(props)}
|
stroke={strokeFilter(props)}
|
||||||
|
x={x}
|
||||||
|
y={y}
|
||||||
/>;
|
/>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user