UNPKG

react-native-svg-charts

Version:

Customizable charts (Line, Bar, Area, Pie, Circle, Progress) for React Native

157 lines (137 loc) 4.74 kB
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] const key = path + '-' + index return ( <Path key={key} 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