From 802e380a5e3d63a4976d8b33be86bf6ae0366390 Mon Sep 17 00:00:00 2001 From: Adam Burdette Date: Fri, 5 Oct 2018 17:33:39 -0400 Subject: [PATCH 1/2] Added grouped lines and story Duplicated Chart but altered it to use the standard grouping data structure and implemented a line gate that produces a path for each line. Also added a story for a grouped set of lines. --- src/area-chart.js | 2 +- src/chart/chart-grouped.js | 165 ++++++++++++++++++++++++ src/{ => chart}/chart.js | 2 +- src/line-chart/index.js | 15 +++ src/line-chart/line-chart-grouped.js | 31 +++++ src/{ => line-chart}/line-chart.js | 2 +- storybook/stories/line-chart/grouped.js | 35 +++++ storybook/stories/line-chart/index.js | 10 +- 8 files changed, 255 insertions(+), 7 deletions(-) create mode 100644 src/chart/chart-grouped.js rename src/{ => chart}/chart.js (99%) create mode 100644 src/line-chart/index.js create mode 100644 src/line-chart/line-chart-grouped.js rename src/{ => line-chart}/line-chart.js (93%) create mode 100644 storybook/stories/line-chart/grouped.js diff --git a/src/area-chart.js b/src/area-chart.js index ac46d8a8..82ac943e 100644 --- a/src/area-chart.js +++ b/src/area-chart.js @@ -1,6 +1,6 @@ import * as shape from 'd3-shape' import PropTypes from 'prop-types' -import Chart from './chart' +import Chart from './chart/chart' class AreaChart extends Chart { diff --git a/src/chart/chart-grouped.js b/src/chart/chart-grouped.js new file mode 100644 index 00000000..aa81ac07 --- /dev/null +++ b/src/chart/chart-grouped.js @@ -0,0 +1,165 @@ +import * as array from 'd3-array' +// import * as scale from 'd3-scale' +// import * as shape from 'd3-shape' +import PropTypes from 'prop-types' +import React, { PureComponent } from 'react' +import { View } from 'react-native' +import Svg from 'react-native-svg' +import Path from '../animated-path' +import Chart from './chart' + +class ChartGrouped extends PureComponent { + + state = { + width: 0, + height: 0, + } + + _onLayout(event) { + const { nativeEvent: { layout: { height, width } } } = event + this.setState({ height, width }) + } + + createPaths() { + throw 'Extending "ChartGrouped" requires you to override "createPaths' + } + + render() { + + const { + data, + xAccessor, + yAccessor, + yScale, + xScale, + style, + animate, + animationDuration, + numberOfTicks, + contentInset: { + top = 0, + bottom = 0, + left = 0, + right = 0, + }, + gridMax, + gridMin, + clampX, + clampY, + svg, + children, + } = this.props + + const { width, height } = this.state + + if (data.length === 0) { + return + } + + const mappedData = data.map((dataArray) => dataArray.data.map((item, index) => ({ + y: yAccessor({ item, index }), + x: xAccessor({ item, index }), + }))) + + const yValues = array.merge(mappedData).map(item => item.y) + const xValues = array.merge(mappedData).map(item => item.x) + + const yExtent = array.extent([ ...yValues, gridMin, gridMax ]) + const xExtent = array.extent([ ...xValues ]) + + const { + yMin = yExtent[0], + yMax = yExtent[1], + xMin = xExtent[0], + xMax = xExtent[1], + } = this.props + + //invert range to support svg coordinate system + const y = yScale() + .domain([ yMin, yMax ]) + .range([ height - bottom, top ]) + .clamp(clampY) + + const x = xScale() + .domain([ xMin, xMax ]) + .range([ left, width - right ]) + .clamp(clampX) + + const paths = this.createPaths({ + data: mappedData, + x, + y, + }) + + const ticks = y.ticks(numberOfTicks) + + const extraProps = { + x, + y, + data, + ticks, + width, + height, + ...paths, + } + + return ( + + this._onLayout(event) }> + { + height > 0 && width > 0 && + + { + React.Children.map(children, child => { + if (child && child.props.belowChart) { + return React.cloneElement(child, extraProps) + } + return null + }) + } + {paths.path.map((path, index) => { + const { svg: pathSvg } = data[index] + return ( + ) + })} + { + React.Children.map(children, child => { + if (child && !child.props.belowChart) { + return React.cloneElement(child, extraProps) + } + return null + }) + } + + } + + + ) + } +} + +ChartGrouped.propTypes = { + ...Chart.propTypes, + data: PropTypes.arrayOf(PropTypes.shape({ + data: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.object), + PropTypes.arrayOf(PropTypes.number), + PropTypes.arrayOf(PropTypes.array), + ]), + svg: PropTypes.object, + })).isRequired, +} + +ChartGrouped.defaultProps = { + ...Chart.defaultProps, +} + +export default ChartGrouped diff --git a/src/chart.js b/src/chart/chart.js similarity index 99% rename from src/chart.js rename to src/chart/chart.js index 22241293..c4fd6728 100644 --- a/src/chart.js +++ b/src/chart/chart.js @@ -5,7 +5,7 @@ import PropTypes from 'prop-types' import React, { PureComponent } from 'react' import { View } from 'react-native' import Svg from 'react-native-svg' -import Path from './animated-path' +import Path from '../animated-path' class Chart extends PureComponent { diff --git a/src/line-chart/index.js b/src/line-chart/index.js new file mode 100644 index 00000000..15637d08 --- /dev/null +++ b/src/line-chart/index.js @@ -0,0 +1,15 @@ +import React from 'react' +import LineChart from './line-chart' +import LineChartGrouped from './line-chart-grouped' + +const LineChartGate = (props) => { + const { data } = props + + if (data[0].hasOwnProperty('data')) { + return + } + + return +} + +export default LineChartGate diff --git a/src/line-chart/line-chart-grouped.js b/src/line-chart/line-chart-grouped.js new file mode 100644 index 00000000..4a974301 --- /dev/null +++ b/src/line-chart/line-chart-grouped.js @@ -0,0 +1,31 @@ +import * as shape from 'd3-shape' +import ChartGrouped from '../chart/chart-grouped' + +class LineChartGrouped extends ChartGrouped { + + createPaths({ data, x, y }) { + const { curve } = this.props + + const lines = data.map((line) => shape.line() + .x((d) => x(d.x)) + .y(d => y(d.y)) + .defined(item => typeof item.y === 'number') + .curve(curve) + (line)) + + return { + path: lines, + lines, + } + } +} + +LineChartGrouped.propTypes = { + ...ChartGrouped.propTypes, +} + +LineChartGrouped.defaultProps = { + ...ChartGrouped.defaultProps, +} + +export default LineChartGrouped diff --git a/src/line-chart.js b/src/line-chart/line-chart.js similarity index 93% rename from src/line-chart.js rename to src/line-chart/line-chart.js index b98e6c10..0a78aca1 100644 --- a/src/line-chart.js +++ b/src/line-chart/line-chart.js @@ -1,5 +1,5 @@ import * as shape from 'd3-shape' -import Chart from './chart' +import Chart from '../chart/chart' class LineChart extends Chart { diff --git a/storybook/stories/line-chart/grouped.js b/storybook/stories/line-chart/grouped.js new file mode 100644 index 00000000..fa3f84ce --- /dev/null +++ b/storybook/stories/line-chart/grouped.js @@ -0,0 +1,35 @@ +import React from 'react' +import { LineChart, Grid } from 'react-native-svg-charts' + +class GroupedLineChartExample extends React.PureComponent { + + render() { + + const data1 = [ 50, 10, 40, 95, -4, -24, 85, 91, 35, 53, -53, 24, 50, -20, -80 ] + const data2 = [ -87, 66, -69, 92, -40, -61, 16, 62, 20, -93, -54, 47, -89, -44, 18 ] + + const data = [ + { + data: data1, + svg: { stroke: '#8800cc' }, + }, + { + data: data2, + svg: { stroke: 'green' }, + }, + ] + + return ( + + + + ) + } + +} + +export default GroupedLineChartExample diff --git a/storybook/stories/line-chart/index.js b/storybook/stories/line-chart/index.js index e851a129..6cd717c4 100644 --- a/storybook/stories/line-chart/index.js +++ b/storybook/stories/line-chart/index.js @@ -4,10 +4,12 @@ import { storiesOf } from '@storybook/react-native' import Standard from './standard' import Partial from './partial' import WithGradient from './with-gradient' +import Grouped from './grouped' import ShowcaseCard from '../showcase-card' storiesOf('LineChart') - .addDecorator(getStory => { getStory() }) - .add('Standard', () => ) - .add('Partial', () => ) - .add('With gradient', () => ) + .addDecorator(getStory => {getStory()}) + .add('Standard', () => ) + .add('Partial', () => ) + .add('With gradient', () => ) + .add('Grouped', () => ) From e891bd6fb370294bb9c57b97f2ea98aa9fed2e9b Mon Sep 17 00:00:00 2001 From: Adam Burdette Date: Fri, 5 Oct 2018 17:33:55 -0400 Subject: [PATCH 2/2] Remove comments Remove commented out extranious imports. --- src/chart/chart-grouped.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/chart/chart-grouped.js b/src/chart/chart-grouped.js index aa81ac07..f6d3552c 100644 --- a/src/chart/chart-grouped.js +++ b/src/chart/chart-grouped.js @@ -1,6 +1,4 @@ import * as array from 'd3-array' -// import * as scale from 'd3-scale' -// import * as shape from 'd3-shape' import PropTypes from 'prop-types' import React, { PureComponent } from 'react' import { View } from 'react-native'