From 50b941c4bcec37d64af75fafd235ab74a9d335b5 Mon Sep 17 00:00:00 2001 From: Horcrux Date: Mon, 25 Jan 2016 18:07:06 +0800 Subject: [PATCH] Add Symbol element refactor viewbox Add Symbol element refactor viewbox --- Example/examples.js | 2 + Example/examples/Svg.js | 1 + Example/examples/Symbol.js | 79 +++++++++++++++++++++++++++++ Example/main.js | 2 +- elements/Svg.js | 101 +++++++------------------------------ elements/Symbol.js | 34 +++++++++++++ elements/ViewBox.js | 47 +++++++++++++++++ index.js | 2 + lib/extractViewbox.js | 71 ++++++++++++++++++++++++++ 9 files changed, 256 insertions(+), 83 deletions(-) create mode 100644 Example/examples/Symbol.js create mode 100644 elements/Symbol.js create mode 100644 elements/ViewBox.js create mode 100644 lib/extractViewbox.js diff --git a/Example/examples.js b/Example/examples.js index a90ced1b..5cd2a8a2 100644 --- a/Example/examples.js +++ b/Example/examples.js @@ -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 }; diff --git a/Example/examples/Svg.js b/Example/examples/Svg.js index 6aa5003d..d0720b01 100644 --- a/Example/examples/Svg.js +++ b/Example/examples/Svg.js @@ -72,6 +72,7 @@ class SvgViewbox extends Component{ height="100" width="100" viewbox="40 20 100 40" + preserveAspectRatio="none" > diff --git a/Example/examples/Symbol.js b/Example/examples/Symbol.js new file mode 100644 index 00000000..1faa486d --- /dev/null +++ b/Example/examples/Symbol.js @@ -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 + + + + + + + + + + ; + } +} + +const icon = + + + + + + + +; + +const samples = [SymbolExample]; + +export { + icon, + samples +} diff --git a/Example/main.js b/Example/main.js index 4ebf7373..fa581bac 100644 --- a/Example/main.js +++ b/Example/main.js @@ -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() { diff --git a/elements/Svg.js b/elements/Svg.js index 245fe2dc..8a271d3f 100644 --- a/elements/Svg.js +++ b/elements/Svg.js @@ -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 - {(!scaleX || !scaleY) ? null : - {this.getChildren()} - } + ; } return + + {props.children} + + + } +} + +export default Symbol; diff --git a/elements/ViewBox.js b/elements/ViewBox.js new file mode 100644 index 00000000..b4d2a287 --- /dev/null +++ b/elements/ViewBox.js @@ -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 + {(!scaleX || !scaleY) ? null : this.props.children} + + } +} + +export default ViewBox; diff --git a/index.js b/index.js index fa60fbca..2301cfda 100644 --- a/index.js +++ b/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, diff --git a/lib/extractViewbox.js b/lib/extractViewbox.js new file mode 100644 index 00000000..c4edecb7 --- /dev/null +++ b/lib/extractViewbox.js @@ -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; +}