mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-21 06:15:15 +00:00
Add Symbol element refactor viewbox
Add Symbol element refactor viewbox
This commit is contained in:
@@ -10,6 +10,7 @@ import * as Text from './examples/Text';
|
||||
import * as G from './examples/G';
|
||||
import * as Stroking from './examples/Stroking';
|
||||
import * as Use from './examples/Use';
|
||||
import * as Symbol from './examples/Symbol';
|
||||
import * as Gradients from './examples/Gradients';
|
||||
|
||||
export {
|
||||
@@ -25,5 +26,6 @@ export {
|
||||
Stroking,
|
||||
G,
|
||||
Use,
|
||||
Symbol,
|
||||
Gradients
|
||||
};
|
||||
|
||||
@@ -72,6 +72,7 @@ class SvgViewbox extends Component{
|
||||
height="100"
|
||||
width="100"
|
||||
viewbox="40 20 100 40"
|
||||
preserveAspectRatio="none"
|
||||
>
|
||||
<Rect x="0" y="0" width="100" height="100" fill="black" />
|
||||
<Circle cx="50" cy="50" r="30" fill="yellow" />
|
||||
|
||||
79
Example/examples/Symbol.js
Normal file
79
Example/examples/Symbol.js
Normal file
@@ -0,0 +1,79 @@
|
||||
import React, {
|
||||
Component
|
||||
} from 'react-native';
|
||||
|
||||
import Svg, {
|
||||
Symbol,
|
||||
Circle,
|
||||
Use
|
||||
} from 'react-native-art-svg';
|
||||
|
||||
class SymbolExample extends Component{
|
||||
static title = 'Symbol example';
|
||||
render() {
|
||||
return <Svg
|
||||
height="150"
|
||||
width="110"
|
||||
>
|
||||
<Symbol id="symbol" viewbox="0 0 150 110">
|
||||
<Circle cx="50" cy="50" r="40" strokeWidth="8" stroke="red" fill="red"/>
|
||||
<Circle cx="90" cy="60" r="40" strokeWidth="8" stroke="green" fill="white"/>
|
||||
</Symbol>
|
||||
|
||||
<Use
|
||||
href="#symbol"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100"
|
||||
height="50"
|
||||
/>
|
||||
<Use
|
||||
href="#symbol"
|
||||
x="0"
|
||||
y="50"
|
||||
width="75"
|
||||
height="38"
|
||||
/>
|
||||
<Use
|
||||
href="#symbol"
|
||||
x="0"
|
||||
y="100"
|
||||
width="50"
|
||||
height="25"
|
||||
/>
|
||||
|
||||
</Svg>;
|
||||
}
|
||||
}
|
||||
|
||||
const icon = <Svg
|
||||
height="20"
|
||||
width="20"
|
||||
>
|
||||
<Symbol id="symbol" viewbox="0 0 150 110">
|
||||
<Circle cx="50" cy="50" r="40" strokeWidth="8" stroke="red" fill="red"/>
|
||||
<Circle cx="90" cy="60" r="40" strokeWidth="8" stroke="green" fill="white"/>
|
||||
</Symbol>
|
||||
|
||||
<Use
|
||||
href="#symbol"
|
||||
x="0"
|
||||
y="0"
|
||||
width="20"
|
||||
height="10"
|
||||
/>
|
||||
<Use
|
||||
href="#symbol"
|
||||
x="0"
|
||||
y="12"
|
||||
width="20"
|
||||
height="8"
|
||||
/>
|
||||
</Svg>;
|
||||
|
||||
const samples = [SymbolExample];
|
||||
|
||||
export {
|
||||
icon,
|
||||
samples
|
||||
}
|
||||
@@ -104,7 +104,7 @@ const styles = StyleSheet.create({
|
||||
}
|
||||
});
|
||||
|
||||
const names = ['Svg', 'Stroking', 'Path', 'Line', 'Rect', 'Polygon', 'Polyline', 'Circle', 'Ellipse', 'G', 'Text', 'Use', 'Gradients'];
|
||||
const names = ['Svg', 'Stroking', 'Path', 'Line', 'Rect', 'Polygon', 'Polyline', 'Circle', 'Ellipse', 'G', 'Text', 'Use', 'Symbol', 'Gradients'];
|
||||
|
||||
class ArtSvgExample extends Component {
|
||||
constructor() {
|
||||
|
||||
@@ -5,74 +5,14 @@ import React, {
|
||||
Children,
|
||||
cloneElement
|
||||
} from 'react-native';
|
||||
|
||||
import extractViewbox from '../lib/extractViewbox';
|
||||
import ViewBox from './ViewBox';
|
||||
import _ from 'lodash';
|
||||
let {
|
||||
Surface,
|
||||
Group
|
||||
} = ART;
|
||||
|
||||
function extractViewbox({viewbox, width, height, preserveAspectRatio}) {
|
||||
if (!viewbox || !width || !height) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof viewbox === 'string') {
|
||||
let parts = viewbox.trim().split(/\s+/);
|
||||
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: 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 false;
|
||||
}
|
||||
|
||||
let id = 0;
|
||||
|
||||
class Svg extends Component{
|
||||
@@ -101,36 +41,33 @@ class Svg extends Component{
|
||||
};
|
||||
|
||||
render() {
|
||||
let opacity = +this.props.opacity;
|
||||
let viewbox = extractViewbox(this.props);
|
||||
if (viewbox) {
|
||||
let {scaleX, scaleY} = viewbox;
|
||||
|
||||
let {props} = this;
|
||||
let opacity = +props.opacity;
|
||||
if (props.viewbox) {
|
||||
return <Surface
|
||||
{...this.props}
|
||||
{...props}
|
||||
style={[
|
||||
this.props.style,
|
||||
props.style,
|
||||
!isNaN(opacity) && {
|
||||
opacity: opacity
|
||||
}
|
||||
]}
|
||||
>
|
||||
{(!scaleX || !scaleY) ? null :
|
||||
<Group
|
||||
x={viewbox.x}
|
||||
y={viewbox.y}
|
||||
scaleX={scaleX}
|
||||
scaleY={scaleY}
|
||||
<ViewBox
|
||||
viewbox={props.viewbox}
|
||||
preserveAspectRatio={props.preserveAspectRatio}
|
||||
width={props.width}
|
||||
height={props.height}
|
||||
>
|
||||
{this.getChildren()}
|
||||
</Group>}
|
||||
</ViewBox>
|
||||
</Surface>;
|
||||
}
|
||||
|
||||
return <Surface
|
||||
{...this.props}
|
||||
{...props}
|
||||
style={[
|
||||
this.props.style,
|
||||
props.style,
|
||||
!isNaN(opacity) && {
|
||||
opacity: opacity
|
||||
}
|
||||
|
||||
34
elements/Symbol.js
Normal file
34
elements/Symbol.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import React, {
|
||||
Component,
|
||||
PropTypes,
|
||||
ART
|
||||
} from 'react-native';
|
||||
|
||||
import ViewBox from './ViewBox';
|
||||
import Defs from './Defs';
|
||||
import extractViewbox from '../lib/extractViewbox';
|
||||
class Symbol extends Component{
|
||||
static displayName = 'Symbol';
|
||||
static propType = {
|
||||
id: PropTypes.string.isRequired
|
||||
};
|
||||
render() {
|
||||
let {props} = this;
|
||||
return <Defs.Item
|
||||
id={props.id}
|
||||
svgId={props.svgId}
|
||||
>
|
||||
<ViewBox
|
||||
viewbox={props.viewbox}
|
||||
preserveAspectRatio={props.preserveAspectRatio}
|
||||
width={props.width}
|
||||
height={props.height}
|
||||
shouldTransform={true}
|
||||
>
|
||||
{props.children}
|
||||
</ViewBox>
|
||||
</Defs.Item>
|
||||
}
|
||||
}
|
||||
|
||||
export default Symbol;
|
||||
47
elements/ViewBox.js
Normal file
47
elements/ViewBox.js
Normal file
@@ -0,0 +1,47 @@
|
||||
import React, {
|
||||
Component,
|
||||
PropTypes,
|
||||
ART
|
||||
} from 'react-native';
|
||||
|
||||
let {
|
||||
Shape,
|
||||
} = ART;
|
||||
|
||||
import G from './G';
|
||||
import extractViewbox from '../lib/extractViewbox';
|
||||
class ViewBox extends Component{
|
||||
static displayName = 'ViewBox';
|
||||
static propType = {
|
||||
transform: PropTypes.bool
|
||||
};
|
||||
static defaultProps = {
|
||||
transform: false
|
||||
};
|
||||
|
||||
render() {
|
||||
let viewbox = extractViewbox(this.props);
|
||||
let scaleX = 1;
|
||||
let scaleY = 1;
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
if (viewbox) {
|
||||
scaleX = viewbox.scaleX;
|
||||
scaleY = viewbox.scaleY;
|
||||
x = viewbox.x;
|
||||
y = viewbox.y;
|
||||
}
|
||||
return <G
|
||||
x={x}
|
||||
y={y}
|
||||
scaleX={scaleX}
|
||||
scaleY={scaleY}
|
||||
id={this.props.id}
|
||||
svgId={this.props.svgId}
|
||||
>
|
||||
{(!scaleX || !scaleY) ? null : this.props.children}
|
||||
</G>
|
||||
}
|
||||
}
|
||||
|
||||
export default ViewBox;
|
||||
2
index.js
2
index.js
@@ -13,6 +13,7 @@ import Path from './elements/Path';
|
||||
import G from './elements/G';
|
||||
import Text from './elements/Text';
|
||||
import Use from './elements/Use';
|
||||
import Symbol from './elements/Symbol';
|
||||
import Defs from './elements/Defs';
|
||||
import LinearGradient from './elements/LinearGradient';
|
||||
import RadialGradient from './elements/RadialGradient';
|
||||
@@ -35,6 +36,7 @@ export {
|
||||
Line,
|
||||
Rect,
|
||||
Use,
|
||||
Symbol,
|
||||
Defs,
|
||||
LinearGradient,
|
||||
RadialGradient,
|
||||
|
||||
71
lib/extractViewbox.js
Normal file
71
lib/extractViewbox.js
Normal file
@@ -0,0 +1,71 @@
|
||||
export default function({viewbox, width, height, preserveAspectRatio, x: dx, y: dy, dScale, dScaleX, dScaleY, shouldTransform}) {
|
||||
if (!viewbox || !width || !height) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof viewbox === 'string') {
|
||||
let parts = viewbox.trim().split(/\s+/);
|
||||
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: 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 = 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];
|
||||
}
|
||||
} else {
|
||||
scaleX = sx;
|
||||
scaleY = sy;
|
||||
x = -vx * sx;
|
||||
y = -vy * sy;
|
||||
}
|
||||
|
||||
if (shouldTransform) {
|
||||
x += (+dx || 0);
|
||||
y += (+dy || 0);
|
||||
|
||||
if (dScale) {
|
||||
scaleX *= (+dScale || 1);
|
||||
scaleY *= (+dScale || 1);
|
||||
} else {
|
||||
scaleX *= (+dScaleX || 1);
|
||||
scaleY *= (+dScaleY || 1);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
x,
|
||||
y,
|
||||
scaleX,
|
||||
scaleY
|
||||
};
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user