Add G example and add viewbox for Svg

Add G example and add viewbox for Svg
This commit is contained in:
Horcrux
2016-01-23 16:08:19 +08:00
parent d40921354b
commit 1fecd0a015
7 changed files with 254 additions and 70 deletions

View File

@@ -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
View 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
}

View File

@@ -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,

View File

@@ -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?

View File

@@ -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>;
}
}

View File

@@ -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
View 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
}
}