Skip to content

Commit

Permalink
Merge pull request #240 from alburdette619/feature/grouped-line-chart…
Browse files Browse the repository at this point in the history
…s-new

Grouped Line Charts
  • Loading branch information
JesperLekland authored Dec 15, 2018
2 parents 230df89 + e891bd6 commit 26e5cc4
Show file tree
Hide file tree
Showing 8 changed files with 253 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src/area-chart.js
Original file line number Diff line number Diff line change
@@ -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 {

Expand Down
163 changes: 163 additions & 0 deletions src/chart/chart-grouped.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import * as array from 'd3-array'
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 <View style={ style } />
}

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 (
<View style={ style }>
<View style={{ flex: 1 }} onLayout={ event => this._onLayout(event) }>
{
height > 0 && width > 0 &&
<Svg style={{ height, width }}>
{
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 (
<Path
key={ path }
fill={ 'none' }
{ ...svg }
{ ...pathSvg }
d={ path }
animate={ animate }
animationDuration={ animationDuration }
/>)
})}
{
React.Children.map(children, child => {
if (child && !child.props.belowChart) {
return React.cloneElement(child, extraProps)
}
return null
})
}
</Svg>
}
</View>
</View>
)
}
}

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
2 changes: 1 addition & 1 deletion src/chart.js → src/chart/chart.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down
15 changes: 15 additions & 0 deletions src/line-chart/index.js
Original file line number Diff line number Diff line change
@@ -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 <LineChartGrouped { ...props } />
}

return <LineChart { ...props } />
}

export default LineChartGate
31 changes: 31 additions & 0 deletions src/line-chart/line-chart-grouped.js
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion src/line-chart.js → src/line-chart/line-chart.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as shape from 'd3-shape'
import Chart from './chart'
import Chart from '../chart/chart'

class LineChart extends Chart {

Expand Down
35 changes: 35 additions & 0 deletions storybook/stories/line-chart/grouped.js
Original file line number Diff line number Diff line change
@@ -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 (
<LineChart
style={{ height: 200 }}
data={ data }
contentInset={{ top: 20, bottom: 20 }}
>
<Grid />
</LineChart>
)
}

}

export default GroupedLineChartExample
10 changes: 6 additions & 4 deletions storybook/stories/line-chart/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 => <ShowcaseCard>{ getStory() }</ShowcaseCard>)
.add('Standard', () => <Standard/>)
.add('Partial', () => <Partial/>)
.add('With gradient', () => <WithGradient/>)
.addDecorator(getStory => <ShowcaseCard>{getStory()}</ShowcaseCard>)
.add('Standard', () => <Standard />)
.add('Partial', () => <Partial />)
.add('With gradient', () => <WithGradient />)
.add('Grouped', () => <Grouped />)

0 comments on commit 26e5cc4

Please sign in to comment.