UNPKG

react-native-svg-charts

Version:

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

242 lines (221 loc) 6.22 kB
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 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'; class BarChart extends PureComponent { constructor(...args) { super(...args); _defineProperty(this, "state", { width: 0, height: 0 }); } _onLayout(event) { const { nativeEvent: { layout: { height, width } } } = event; this.setState({ height, width }); } calcXScale(domain) { const { horizontal, contentInset: { left = 0, right = 0 }, spacingInner, spacingOuter, clamp } = this.props; const { width } = this.state; if (horizontal) { return scale.scaleLinear().domain(domain).range([left, width - right]).clamp(clamp); } return scale.scaleBand().domain(domain).range([left, width - right]).paddingInner([spacingInner]).paddingOuter([spacingOuter]); } calcYScale(domain) { const { horizontal, contentInset: { top = 0, bottom = 0 }, spacingInner, spacingOuter, clamp } = this.props; const { height } = this.state; if (horizontal) { return scale.scaleBand().domain(domain).range([top, height - bottom]).paddingInner([spacingInner]).paddingOuter([spacingOuter]); } return scale.scaleLinear().domain(domain).range([height - bottom, top]).clamp(clamp); } calcAreas(x, y) { const { horizontal, data, yAccessor } = this.props; const values = data.map(item => yAccessor({ item })); if (horizontal) { return data.map((bar, index) => ({ bar, path: shape.area().y((value, _index) => _index === 0 ? y(index) : y(index) + y.bandwidth()).x0(x(0)).x1(value => x(value)).defined(value => typeof value === 'number')([values[index], values[index]]) })); } return data.map((bar, index) => ({ bar, path: shape.area().y0(y(0)).y1(value => y(value)).x((value, _index) => _index === 0 ? x(index) : x(index) + x.bandwidth()).defined(value => typeof value === 'number')([values[index], values[index]]) })); } calcExtent() { const { data, gridMin, gridMax, yAccessor } = this.props; const values = data.map(obj => yAccessor({ item: obj })); const extent = array.extent([...values, gridMax, gridMin]); const { yMin = extent[0], yMax = extent[1] } = this.props; return [yMin, yMax]; } calcIndexes() { const { data } = this.props; return data.map((_, index) => index); } render() { const { data, animate, animationDuration, style, numberOfTicks, svg, horizontal, children } = this.props; const { height, width } = this.state; if (data.length === 0) { return /*#__PURE__*/React.createElement(View, { style: style }); } const extent = this.calcExtent(); const indexes = this.calcIndexes(); const ticks = array.ticks(extent[0], extent[1], numberOfTicks); const xDomain = horizontal ? extent : indexes; const yDomain = horizontal ? indexes : extent; const x = this.calcXScale(xDomain); const y = this.calcYScale(yDomain); const bandwidth = horizontal ? y.bandwidth() : x.bandwidth(); const areas = this.calcAreas(x, y).filter(area => area.bar !== null && area.bar !== undefined && area.path !== null); const extraProps = { x, y, width, height, bandwidth, ticks, data }; return /*#__PURE__*/React.createElement(View, { style: style }, /*#__PURE__*/React.createElement(View, { style: { flex: 1 }, onLayout: event => this._onLayout(event) }, height > 0 && width > 0 && /*#__PURE__*/React.createElement(Svg, { style: { height, width } }, React.Children.map(children, child => { if (child && child.props.belowChart) { return React.cloneElement(child, extraProps); } }), areas.map((area, index) => { const { bar: { svg: barSvg = {} }, path } = area; return /*#__PURE__*/React.createElement(Path, _extends({ key: index }, svg, barSvg, { d: path, animate: animate, animationDuration: animationDuration })); }), React.Children.map(children, child => { if (child && !child.props.belowChart) { return React.cloneElement(child, extraProps); } })))); } } BarChart.propTypes = { data: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.object])).isRequired, style: PropTypes.any, spacingInner: PropTypes.number, spacingOuter: PropTypes.number, animate: PropTypes.bool, animationDuration: PropTypes.number, contentInset: PropTypes.shape({ top: PropTypes.number, left: PropTypes.number, right: PropTypes.number, bottom: PropTypes.number }), numberOfTicks: PropTypes.number, gridMin: PropTypes.number, gridMax: PropTypes.number, svg: PropTypes.object, yMin: PropTypes.any, yMax: PropTypes.any, clamp: PropTypes.bool }; BarChart.defaultProps = { spacingInner: 0.05, spacingOuter: 0.05, contentInset: {}, numberOfTicks: 10, svg: {}, yAccessor: ({ item }) => item }; export default BarChart; //# sourceMappingURL=bar-chart.js.map