From 1fecd0a015532cea861b1f706729954a0e255a35 Mon Sep 17 00:00:00 2001 From: Horcrux Date: Sat, 23 Jan 2016 16:08:19 +0800 Subject: [PATCH] Add G example and add viewbox for Svg Add G example and add viewbox for Svg --- Example/examples.js | 4 +- Example/examples/G.js | 131 ++++++++++++++++++++++++++++++++++++++++ Example/examples/Svg.js | 51 ++++++---------- README.md | 7 --- elements/G.js | 3 + elements/Svg.js | 115 +++++++++++++++++++++++++---------- lib/transformFilter.js | 13 ++++ 7 files changed, 254 insertions(+), 70 deletions(-) create mode 100644 Example/examples/G.js create mode 100644 lib/transformFilter.js diff --git a/Example/examples.js b/Example/examples.js index eeccf707..1d1cbfa7 100644 --- a/Example/examples.js +++ b/Example/examples.js @@ -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 }; diff --git a/Example/examples/G.js b/Example/examples/G.js new file mode 100644 index 00000000..4c591002 --- /dev/null +++ b/Example/examples/G.js @@ -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 + + + + + + + + ; + } +} + +class GTransform extends Component{ + static title = 'G transform'; + render() { + return + + + + + + + Text grouped with shapes + + ; + } +} + +const icon = + + + + + + + +; + +const samples = [GExample, GTransform]; + +export { + icon, + samples +} diff --git a/Example/examples/Svg.js b/Example/examples/Svg.js index 038caba0..6aa5003d 100644 --- a/Example/examples/Svg.js +++ b/Example/examples/Svg.js @@ -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 - - - ; - } -} - 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 + + + + + + ; + } +} + const icon = ; -const samples = [SvgExample, SvgOpacity]; +const samples = [SvgExample, SvgOpacity ,SvgViewbox]; export { icon, diff --git a/README.md b/README.md index 504cf518..879c7c79 100644 --- a/README.md +++ b/README.md @@ -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? diff --git a/elements/G.js b/elements/G.js index 55b56561..ac63059e 100644 --- a/elements/G.js +++ b/elements/G.js @@ -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 {this.children}; } } diff --git a/elements/Svg.js b/elements/Svg.js index f385d67b..132204a3 100644 --- a/elements/Svg.js +++ b/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 + {(!scaleX || !scaleY) ? null : + + {this.props.children} + } + ; + } + return - - {this.props.children} - + {this.props.children} ; } } diff --git a/lib/transformFilter.js b/lib/transformFilter.js new file mode 100644 index 00000000..d5428341 --- /dev/null +++ b/lib/transformFilter.js @@ -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 + } +}