mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-06 07:06:11 +00:00
Add G example and add viewbox for Svg
Add G example and add viewbox for Svg
This commit is contained in:
@@ -7,6 +7,7 @@ import * as Polygon from './examples/Polygon';
|
||||
import * as Polyline from './examples/Polyline';
|
||||
import * as Path from './examples/Path';
|
||||
import * as Text from './examples/Text';
|
||||
import * as G from './examples/G';
|
||||
|
||||
export {
|
||||
Svg,
|
||||
@@ -17,5 +18,6 @@ export {
|
||||
Polygon,
|
||||
Polyline,
|
||||
Path,
|
||||
Text
|
||||
Text,
|
||||
G
|
||||
};
|
||||
|
||||
131
Example/examples/G.js
Normal file
131
Example/examples/G.js
Normal file
@@ -0,0 +1,131 @@
|
||||
import React, {
|
||||
Component
|
||||
} from 'react-native';
|
||||
|
||||
import Svg, {
|
||||
G,
|
||||
Circle,
|
||||
Line,
|
||||
Rect,
|
||||
Text
|
||||
} from 'react-native-art-svg';
|
||||
|
||||
class GExample extends Component{
|
||||
static title = 'G children props inherit';
|
||||
render() {
|
||||
return <Svg
|
||||
height="100"
|
||||
width="100"
|
||||
>
|
||||
<G
|
||||
r="11"
|
||||
fill="purple"
|
||||
stroke="pink"
|
||||
strokeWidth="3"
|
||||
>
|
||||
<Circle
|
||||
cx="25"
|
||||
cy="25"
|
||||
/>
|
||||
<Circle
|
||||
cx="25"
|
||||
cy="75"
|
||||
/>
|
||||
<Circle
|
||||
cx="50"
|
||||
cy="50"
|
||||
fill="green"
|
||||
/>
|
||||
<Circle
|
||||
cx="75"
|
||||
cy="25"
|
||||
/>
|
||||
<Circle
|
||||
cx="75"
|
||||
cy="75"
|
||||
/>
|
||||
</G>
|
||||
</Svg>;
|
||||
}
|
||||
}
|
||||
|
||||
class GTransform extends Component{
|
||||
static title = 'G transform';
|
||||
render() {
|
||||
return <Svg
|
||||
height="100"
|
||||
width="200"
|
||||
>
|
||||
<G
|
||||
rotate="50"
|
||||
origin="100, 50"
|
||||
>
|
||||
<Line
|
||||
x1="60"
|
||||
y1="10"
|
||||
x2="140"
|
||||
y2="10"
|
||||
stroke="#060"
|
||||
/>
|
||||
|
||||
<Rect
|
||||
x="60"
|
||||
y="20"
|
||||
height="50"
|
||||
width="80"
|
||||
stroke="#060"
|
||||
fill="#060"
|
||||
/>
|
||||
|
||||
<Text
|
||||
x="100"
|
||||
y="75"
|
||||
stroke="#600"
|
||||
fill="#600"
|
||||
textAnchor="center"
|
||||
>
|
||||
Text grouped with shapes</Text>
|
||||
</G>
|
||||
</Svg>;
|
||||
}
|
||||
}
|
||||
|
||||
const icon = <Svg
|
||||
height="20"
|
||||
width="20"
|
||||
>
|
||||
<G
|
||||
r="3"
|
||||
fill="purple"
|
||||
stroke="pink"
|
||||
>
|
||||
<Circle
|
||||
cx="5"
|
||||
cy="5"
|
||||
/>
|
||||
<Circle
|
||||
cx="5"
|
||||
cy="15"
|
||||
/>
|
||||
<Circle
|
||||
cx="10"
|
||||
cy="10"
|
||||
fill="green"
|
||||
/>
|
||||
<Circle
|
||||
cx="15"
|
||||
cy="5"
|
||||
/>
|
||||
<Circle
|
||||
cx="15"
|
||||
cy="15"
|
||||
/>
|
||||
</G>
|
||||
</Svg>;
|
||||
|
||||
const samples = [GExample, GTransform];
|
||||
|
||||
export {
|
||||
icon,
|
||||
samples
|
||||
}
|
||||
@@ -4,7 +4,8 @@ import React, {
|
||||
|
||||
import Svg, {
|
||||
Circle,
|
||||
Rect
|
||||
Rect,
|
||||
Path
|
||||
} from 'react-native-art-svg';
|
||||
|
||||
class SvgExample extends Component{
|
||||
@@ -35,35 +36,6 @@ 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{
|
||||
static title = 'SVG with `opacity` prop';
|
||||
render() {
|
||||
@@ -93,6 +65,23 @@ class SvgOpacity extends Component{
|
||||
}
|
||||
}
|
||||
|
||||
class SvgViewbox extends Component{
|
||||
static title = 'SVG with `viewbox="40 20 100 40"`';
|
||||
render() {
|
||||
return <Svg
|
||||
height="100"
|
||||
width="100"
|
||||
viewbox="40 20 100 40"
|
||||
>
|
||||
<Rect x="0" y="0" width="100" height="100" fill="black" />
|
||||
<Circle cx="50" cy="50" r="30" fill="yellow" />
|
||||
<Circle cx="40" cy="40" r="4" fill="black" />
|
||||
<Circle cx="60" cy="40" r="4" fill="black" />
|
||||
<Path d="M 40 60 A 10 10 0 0 0 60 60" stroke="black" />
|
||||
</Svg>;
|
||||
}
|
||||
}
|
||||
|
||||
const icon = <Svg
|
||||
height="20"
|
||||
width="20"
|
||||
@@ -116,7 +105,7 @@ const icon = <Svg
|
||||
/>
|
||||
</Svg>;
|
||||
|
||||
const samples = [SvgExample, SvgOpacity];
|
||||
const samples = [SvgExample, SvgOpacity ,SvgViewbox];
|
||||
|
||||
export {
|
||||
icon,
|
||||
|
||||
@@ -4,23 +4,16 @@
|
||||
TODO:
|
||||
1. fill-rule:evenodd
|
||||
2. gradients
|
||||
3. text
|
||||
4. other elements
|
||||
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?
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ const transformProps = {
|
||||
originY: null
|
||||
};
|
||||
|
||||
import transformFilter from '../lib/transformFilter';
|
||||
|
||||
class G extends Component{
|
||||
static displayName = 'G';
|
||||
|
||||
@@ -38,6 +40,7 @@ class G extends Component{
|
||||
render() {
|
||||
return <Group
|
||||
{...this.props}
|
||||
{...transformFilter(this.props)}
|
||||
>{this.children}</Group>;
|
||||
}
|
||||
}
|
||||
|
||||
115
elements/Svg.js
115
elements/Svg.js
@@ -7,46 +7,106 @@ import React, {
|
||||
import _ from 'lodash';
|
||||
let {
|
||||
Surface,
|
||||
ClippingRectangle
|
||||
} = ART;
|
||||
Group
|
||||
} = ART;
|
||||
|
||||
function extractViewbox({viewbox, width, height, preserveAspectRatio}) {
|
||||
if (!viewbox || !width || !height) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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) {
|
||||
let vw = +parts[2];
|
||||
let vh = +parts[3];
|
||||
|
||||
// width or height can`t be negative
|
||||
if (vw < 0 || vh < 0 || parts.length !== 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// width or height equals zero disable render
|
||||
if (!vw || !vh) {
|
||||
return {
|
||||
x: parts[0],
|
||||
y: parts[1],
|
||||
width: parts[2],
|
||||
height: parts[3]
|
||||
x: 0,
|
||||
y: 0,
|
||||
scaleX: 0,
|
||||
scaleY: 0
|
||||
}
|
||||
}
|
||||
|
||||
let vx = +parts[0] || 0;
|
||||
let vy = +parts[1] || 0;
|
||||
let preserve = preserveAspectRatio !== 'none';
|
||||
let scaleX = 1;
|
||||
let scaleY = 1;
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
let sx = width / vw;
|
||||
let sy = height / vh;
|
||||
|
||||
if (preserve) {
|
||||
scaleX = sx;
|
||||
scaleY = sy;
|
||||
x = -vx * sx;
|
||||
y = -vy * sy;
|
||||
} else {
|
||||
scaleX = scaleY = Math.min(sx, sy);
|
||||
x = width / 2 - Math.min(vw, vh) * scaleX / 2 - vx * scaleX;
|
||||
y = 0 - vy * scaleX;
|
||||
|
||||
if (sx < sy) {
|
||||
[x, y] = [y, x];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
x,
|
||||
y,
|
||||
scaleX,
|
||||
scaleY
|
||||
};
|
||||
}
|
||||
return {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height
|
||||
};
|
||||
return false;
|
||||
}
|
||||
|
||||
class Svg extends Component{
|
||||
static displayName = 'Svg';
|
||||
static propType = {
|
||||
opacity: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
viewbox: PropTypes.string
|
||||
viewbox: PropTypes.string,
|
||||
// TODO: complete other values of preserveAspectRatio
|
||||
preserveAspectRatio: PropTypes.string // preserveAspectRatio only supports 'none' for now
|
||||
};
|
||||
|
||||
render() {
|
||||
let opacity = +this.props.opacity;
|
||||
let {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height
|
||||
} = extractViewbox(this.props);
|
||||
let viewbox = extractViewbox(this.props);
|
||||
if (viewbox) {
|
||||
let {scaleX, scaleY} = viewbox;
|
||||
|
||||
return <Surface
|
||||
{...this.props}
|
||||
style={[
|
||||
this.props.style,
|
||||
!isNaN(opacity) && {
|
||||
opacity: opacity
|
||||
}
|
||||
]}
|
||||
>
|
||||
{(!scaleX || !scaleY) ? null :
|
||||
<Group
|
||||
x={viewbox.x}
|
||||
y={viewbox.y}
|
||||
scaleX={scaleX}
|
||||
scaleY={scaleY}
|
||||
>
|
||||
{this.props.children}
|
||||
</Group>}
|
||||
</Surface>;
|
||||
}
|
||||
|
||||
return <Surface
|
||||
{...this.props}
|
||||
style={[
|
||||
@@ -56,14 +116,7 @@ class Svg extends Component{
|
||||
}
|
||||
]}
|
||||
>
|
||||
<ClippingRectangle
|
||||
x={x}
|
||||
y={y}
|
||||
width={width}
|
||||
height={height}
|
||||
>
|
||||
{this.props.children}
|
||||
</ClippingRectangle>
|
||||
{this.props.children}
|
||||
</Surface>;
|
||||
}
|
||||
}
|
||||
|
||||
13
lib/transformFilter.js
Normal file
13
lib/transformFilter.js
Normal file
@@ -0,0 +1,13 @@
|
||||
export default function (props) {
|
||||
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 {
|
||||
rotation: props.rotation || props.rotate || 0,
|
||||
scale: props.scale || 1,
|
||||
originX,
|
||||
originY
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user