From f203649f639c9600a11f5685decbce8bed4bc0c2 Mon Sep 17 00:00:00 2001 From: MW00 Date: Fri, 22 Mar 2019 11:30:32 +0100 Subject: [PATCH 01/12] Updated README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 73d97e2d..eec44099 100644 --- a/README.md +++ b/README.md @@ -220,6 +220,7 @@ const data = [ accessor="population" backgroundColor="transparent" paddingLeft="15" + absolute /> ``` @@ -232,6 +233,7 @@ const data = [ | accessor | string | Property in the `data` object from which the number values are taken | | bgColor | string | background color - if you want to set transparent, input `transparent` or `none`. | | paddingLeft | string | left padding of the pie chart | +| absolute | boolean | shows the values as absolute numbers | ## Contribution graph (heatmap) From 1afb69870d46b2525941e146d490c4d73f882235 Mon Sep 17 00:00:00 2001 From: MW00 Date: Mon, 25 Mar 2019 12:34:45 +0100 Subject: [PATCH 02/12] Add StackedBar Factor Added a factor to correct Vertical Labels --- src/abstract-chart.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/abstract-chart.js b/src/abstract-chart.js index 1dc392d1..95dce6fa 100644 --- a/src/abstract-chart.js +++ b/src/abstract-chart.js @@ -66,11 +66,15 @@ class AbstractChart extends Component { renderVerticalLabels = config => { const { labels = [], width, height, paddingRight, paddingTop, horizontalOffset = 0 } = config const fontSize = 12 + var fac = 1; + if(stackedBar){ + fac = 0.71 + } return labels.map((label, i) => { return ( Date: Mon, 25 Mar 2019 12:35:30 +0100 Subject: [PATCH 03/12] Create stackedbar-chart --- src/stackedbar-chart.js | 171 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 src/stackedbar-chart.js diff --git a/src/stackedbar-chart.js b/src/stackedbar-chart.js new file mode 100644 index 00000000..9c33675d --- /dev/null +++ b/src/stackedbar-chart.js @@ -0,0 +1,171 @@ + import React from 'react' +import { View } from 'react-native' +import { + Svg, + Rect, + G, + Text, + Path +} from 'react-native-svg' +import AbstractChart from './abstract-chart' + +const barWidth = 32 + +class StackedBarChart extends AbstractChart { + + renderBars = config => { + const { data, width, height, paddingTop, paddingRight, border, colors } = config + return data.map((x, i) => { + //for(g = 0; g + ); + ret.push( + {x[z]} + + ); + + st -= h; + } + return ret; + + + }) + } + + renderLegend = config => { + const {legend, colors, width, height} = config; + return legend.map((x, i) =>{ + return ( + + + + + {x} + + + + ) + }) + + } + + render() { + const paddingTop = 15 + const paddingRight = 50 + const { width, height, style = {}, borders, data } = this.props + const { borderRadius = 0 } = style + const config = { + width, + height + } + var border = 0; + for(let i = 0; i pv + cv, 0); + if(actual > border){ + border = actual; + } + } + + return ( + + + {this.renderDefs({ + ...config, + ...this.props.chartConfig + })} + + + {this.renderHorizontalLines({ + ...config, + count: 4, + paddingTop + })} + + + + + {this.renderHorizontalLabels({ + ...config, + count: 4, + data: [0, border], + paddingTop, + paddingRight + })} + + + {this.renderVerticalLabels({ + ...config, + labels: data.labels, + paddingRight: paddingRight+28, + stackedBar: true, + paddingTop, + horizontalOffset: barWidth + })} + + + {this.renderBars({ + ...config, + data: data.data, + border: border, + colors: this.props.chartConfig.barColors, + paddingTop, + paddingRight: (paddingRight+20) + })} + + {this.renderLegend({ + ...config, + legend: data.legend, + colors: this.props.chartConfig.barColors, + })} + + + ) + } +} +export default StackedBarChart From 9468ef60baa3dab950a49a07a461942b1847d4e2 Mon Sep 17 00:00:00 2001 From: MW00 Date: Mon, 25 Mar 2019 12:36:39 +0100 Subject: [PATCH 04/12] Add StackedBarChart to index.js --- index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 60c1647d..2199fb36 100644 --- a/index.js +++ b/index.js @@ -4,6 +4,7 @@ import BarChart from './src/bar-chart' import PieChart from './src/pie-chart' import ProgressChart from './src/progress-chart' import ContributionGraph from './src/contribution-graph' +import StackedBarChart from './src/stackedbar-chart' export { AbstractChart, @@ -11,5 +12,6 @@ export { LineChart, PieChart, ProgressChart, - ContributionGraph + ContributionGraph, + StackedBarChart } From 917b09a655563ec1056656b22e8074af38ca401d Mon Sep 17 00:00:00 2001 From: MW00 Date: Mon, 25 Mar 2019 12:50:23 +0100 Subject: [PATCH 05/12] Add StackedBarChart to README.md --- README.md | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index eec44099..e84132b2 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,8 @@ import { BarChart, PieChart, ProgressChart, - ContributionGraph + ContributionGraph, + StackedBarChart } from 'react-native-chart-kit' ``` @@ -195,6 +196,38 @@ const data = { | height | Number | Height of the chart | | chartConfig | Object | Configuration object for the chart, see example config in the beginning of this file | +## StackedBar chart + +![StackedBar_Chart](https://imgur.com/JkBtxt8.jpg) + +```js +const data ={ + labels: ['Test1', 'Test2'], + legend: ['L1', 'L2', 'L3'], + data: [ + [60, 60, 60], + [30,30,60], + ], + barColors: ['#dfe4ea', '#ced6e0', '#a4b0be'], + } +``` +```html + +``` + +| Property | Type | Description | +| ------------- |-------------| -----| +| data | Object | Data for the chart - see example above | +| width | Number | Width of the chart, use 'Dimensions' library to get the width of your screen for responsive | +| height | Number | Height of the chart | +| chartConfig | Object | Configuration object for the chart, see example config in the beginning of this file | + ## Pie chart ![Pie Chart](https://i.imgur.com/JMz3obk.jpg) From 1798eac15526b35ff68b333eb7b136707e66c764 Mon Sep 17 00:00:00 2001 From: MW00 Date: Mon, 25 Mar 2019 13:13:46 +0100 Subject: [PATCH 06/12] Added stackedBar Var --- src/abstract-chart.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/abstract-chart.js b/src/abstract-chart.js index 95dce6fa..59700497 100644 --- a/src/abstract-chart.js +++ b/src/abstract-chart.js @@ -64,7 +64,7 @@ class AbstractChart extends Component { } renderVerticalLabels = config => { - const { labels = [], width, height, paddingRight, paddingTop, horizontalOffset = 0 } = config + const { labels = [], width, height, paddingRight, paddingTop, horizontalOffset = 0, stackedBar = false } = config const fontSize = 12 var fac = 1; if(stackedBar){ From f3bb3105dd0045468be9234529771cf6a0c54555 Mon Sep 17 00:00:00 2001 From: MW00 Date: Mon, 25 Mar 2019 13:32:40 +0100 Subject: [PATCH 07/12] Resolve Conflicts --- src/abstract-chart.js | 167 +++++++++++++++++++++++++++--------------- 1 file changed, 109 insertions(+), 58 deletions(-) diff --git a/src/abstract-chart.js b/src/abstract-chart.js index 59700497..22692681 100644 --- a/src/abstract-chart.js +++ b/src/abstract-chart.js @@ -1,26 +1,20 @@ -import React, { Component } from 'react' +import React, {Component} from 'react' -import { - LinearGradient, - Line, - Text, - Defs, - Stop -} from 'react-native-svg' +import {LinearGradient, Line, Text, Defs, Stop} from 'react-native-svg' class AbstractChart extends Component { - calcScaler = data => (Math.max(...data) - Math.min(...data)) || 1 + calcScaler = data => Math.max(...data) - Math.min(...data) || 1 renderHorizontalLines = config => { - const { count, width, height, paddingTop, paddingRight } = config + const {count, width, height, paddingTop, paddingRight} = config return [...new Array(count)].map((_, i) => { return ( { - const { width, height, paddingTop, paddingRight } = config - return ( - - ) - }; + const {width, height, paddingTop, paddingRight} = config + return ( + + ) + } renderHorizontalLabels = config => { - const { count, data, height, paddingTop, paddingRight, yLabelsOffset = 12 } = config - var decimalPlaces = (this.props.chartConfig.decimalPlaces !== undefined) ? this.props.chartConfig.decimalPlaces : 2; + const { + count, + data, + height, + paddingTop, + paddingRight, + yLabelsOffset = 12 + } = config + const decimalPlaces = this.props.chartConfig.decimalPlaces || 2 + const yAxisLabel = this.props.yAxisLabel || '' + return [...new Array(count)].map((_, i) => { + let yLabel + + if (count === 1) { + yLabel = `${yAxisLabel}${data[0].toFixed(decimalPlaces)}` + } else { + const label = + (this.calcScaler(data) / (count - 1)) * i + Math.min(...data) + yLabel = `${yAxisLabel}${label.toFixed(decimalPlaces)}` + } + return ( {count === 1 ? data[0].toFixed(decimalPlaces) : ((this.calcScaler(data) / (count - 1)) * i + Math.min(...data)).toFixed(decimalPlaces)} + > + {yLabel} ) }) } renderVerticalLabels = config => { - const { labels = [], width, height, paddingRight, paddingTop, horizontalOffset = 0, stackedBar = false } = config + const { + labels = [], + width, + height, + paddingRight, + paddingTop, + horizontalOffset = 0, + stackedBar = false + } = config const fontSize = 12 var fac = 1; if(stackedBar){ @@ -74,27 +96,36 @@ class AbstractChart extends Component { return ( {label} + > + {label} ) }) } renderVerticalLines = config => { - const { data, width, height, paddingTop, paddingRight } = config + const {data, width, height, paddingTop, paddingRight} = config return [...new Array(data.length)].map((_, i) => { return ( { - const { height, paddingTop, paddingRight } = config - return ( - - ) + const {height, paddingTop, paddingRight} = config + return ( + + ) } renderDefs = config => { - const { width, height, backgroundGradientFrom, backgroundGradientTo } = config + const {width, height, backgroundGradientFrom, backgroundGradientTo} = config return ( - - - + + + - - - + + + ) From 82f0b298a9c1ccd97b5e1749967b40cebffd909d Mon Sep 17 00:00:00 2001 From: MW00 Date: Mon, 25 Mar 2019 14:07:14 +0100 Subject: [PATCH 08/12] Inverted Legend Inverted Legend that it fit to the StackedBar order. --- src/stackedbar-chart.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stackedbar-chart.js b/src/stackedbar-chart.js index 9c33675d..60acb155 100644 --- a/src/stackedbar-chart.js +++ b/src/stackedbar-chart.js @@ -71,13 +71,13 @@ class StackedBarChart extends AbstractChart { rx={8} ry={8} x={width*0.71} - y={height*0.25+(i)*50} + y={height*0.70-(i)*50} /> + y={height*0.75-(i)*50}> {x} From d0f3d65cd9c0cf994ced5968b7d1836e7bb9195f Mon Sep 17 00:00:00 2001 From: MW00 Date: Mon, 25 Mar 2019 14:09:40 +0100 Subject: [PATCH 09/12] Improve Y Value --- src/stackedbar-chart.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stackedbar-chart.js b/src/stackedbar-chart.js index 60acb155..f8ad9ae5 100644 --- a/src/stackedbar-chart.js +++ b/src/stackedbar-chart.js @@ -77,7 +77,7 @@ class StackedBarChart extends AbstractChart { fill={'#fff'} fontSize={16} x={width*0.78} - y={height*0.75-(i)*50}> + y={height*0.76-(i)*50}> {x} From a35142ce0cd4da2b99fb45af6f70e7c9ae703d09 Mon Sep 17 00:00:00 2001 From: MW00 Date: Mon, 25 Mar 2019 14:46:40 +0100 Subject: [PATCH 10/12] Try to repair the wrong Tab size The first commit has a wrong Tab Size --- src/abstract-chart.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/abstract-chart.js b/src/abstract-chart.js index 22692681..9a19f6c7 100644 --- a/src/abstract-chart.js +++ b/src/abstract-chart.js @@ -85,7 +85,7 @@ class AbstractChart extends Component { paddingRight, paddingTop, horizontalOffset = 0, - stackedBar = false + stackedBar = false, } = config const fontSize = 12 var fac = 1; From 47cf56255e2ccd136de032b5bc31f5586fabdd04 Mon Sep 17 00:00:00 2001 From: MW00 Date: Tue, 26 Mar 2019 15:20:02 +0100 Subject: [PATCH 11/12] Correct Label position when Stack is to small --- src/stackedbar-chart.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stackedbar-chart.js b/src/stackedbar-chart.js index f8ad9ae5..4cf16270 100644 --- a/src/stackedbar-chart.js +++ b/src/stackedbar-chart.js @@ -43,7 +43,7 @@ class StackedBarChart extends AbstractChart { key={Math.random()} x={xC+7+barWidth/2} textAnchor="end" - y={y+18} + y={(h>15) ? (y+15) : (y+7)} fontSize={12} fill='#fff' >{x[z]} From 907f67629acbd2b629a17e84fa8d843e15b65d28 Mon Sep 17 00:00:00 2001 From: Herman Starikov Date: Sun, 31 Mar 2019 21:59:18 -0400 Subject: [PATCH 12/12] fix lint errors, add example into the app --- App.js | 25 ++++- data.js | 118 ++++++++++++-------- package.json | 4 +- src/abstract-chart.js | 12 +- src/stackedbar-chart.js | 237 ++++++++++++++++++++-------------------- 5 files changed, 217 insertions(+), 179 deletions(-) diff --git a/App.js b/App.js index f7538e5c..89854d5a 100644 --- a/App.js +++ b/App.js @@ -1,14 +1,21 @@ import 'babel-polyfill' import React from 'react' -import {ScrollView, StatusBar, Dimensions, Text, View} from 'react-native' +import {ScrollView, StatusBar, Dimensions, Text} from 'react-native' import ScrollableTabView from 'react-native-scrollable-tab-view' import FlashMessage, {showMessage} from 'react-native-flash-message' import LineChart from './src/line-chart' import PieChart from './src/pie-chart' import ProgressChart from './src/progress-chart' import BarChart from './src/bar-chart' +import StackedBarChart from './src/stackedbar-chart' import ContributionGraph from './src/contribution-graph' -import {data, contributionData, pieChartData, progressChartData} from './data' +import { + data, + contributionData, + pieChartData, + progressChartData, + stackedBarGraphData +} from './data' // in Expo - swipe left to see the following styling, or create your own const chartConfigs = [ @@ -117,7 +124,7 @@ export default class App extends React.Component { data={data} width={width} height={height} - yAxisLabel={'$'} + yAxisLabel="$" chartConfig={chartConfig} style={graphStyle} onDataPointClick={({value, getColor}) => @@ -142,10 +149,18 @@ export default class App extends React.Component { width={width} height={height} data={data} - yAxisLabel={'$'} + yAxisLabel="$" chartConfig={chartConfig} style={graphStyle} /> + Stacked Bar Graph + Pie Chart diff --git a/data.js b/data.js index 426e61bc..1b00817d 100644 --- a/data.js +++ b/data.js @@ -2,65 +2,91 @@ const data = { labels: ['January', 'February', 'March', 'April', 'May', 'June'], - datasets: [{ - data: [ - 50, - 20, - 2, - 86, - 71, - 100 - ], - color: (opacity = 1) => `rgba(134, 65, 244, ${opacity})` // optional - }, { - data: [ - 20, - 10, - 4, - 56, - 87, - 90 - ] - }, { - data: [ - 30, - 90, - 67, - 54, - 10, - 2 - ] - }] + datasets: [ + { + data: [50, 20, 2, 86, 71, 100], + color: (opacity = 1) => `rgba(134, 65, 244, ${opacity})` // optional + }, + { + data: [20, 10, 4, 56, 87, 90] + }, + { + data: [30, 90, 67, 54, 10, 2] + } + ] } // Mock data object used for Contribution Graph const contributionData = [ - { date: '2016-01-02', count: 1 }, - { date: '2016-01-03', count: 2 }, - { date: '2016-01-04', count: 3 }, - { date: '2016-01-05', count: 4 }, - { date: '2016-01-06', count: 5 }, - { date: '2016-01-30', count: 2 }, - { date: '2016-01-31', count: 3 }, - { date: '2016-03-01', count: 2 }, - { date: '2016-04-02', count: 4 }, - { date: '2016-03-05', count: 2 }, - { date: '2016-02-30', count: 4 } + {date: '2016-01-02', count: 1}, + {date: '2016-01-03', count: 2}, + {date: '2016-01-04', count: 3}, + {date: '2016-01-05', count: 4}, + {date: '2016-01-06', count: 5}, + {date: '2016-01-30', count: 2}, + {date: '2016-01-31', count: 3}, + {date: '2016-03-01', count: 2}, + {date: '2016-04-02', count: 4}, + {date: '2016-03-05', count: 2}, + {date: '2016-02-30', count: 4} ] // Mock data object for Pie Chart const pieChartData = [ - { name: 'Seoul', population: 21500000, color: 'rgba(131, 167, 234, 1)', legendFontColor: '#7F7F7F', legendFontSize: 15 }, - { name: 'Toronto', population: 2800000, color: '#F00', legendFontColor: '#7F7F7F', legendFontSize: 15 }, - { name: 'Beijing', population: 527612, color: 'red', legendFontColor: '#7F7F7F', legendFontSize: 15 }, - { name: 'New York', population: 8538000, color: '#ffffff', legendFontColor: '#7F7F7F', legendFontSize: 15 }, - { name: 'Moscow', population: 11920000, color: 'rgb(0, 0, 255)', legendFontColor: '#7F7F7F', legendFontSize: 15 } + { + name: 'Seoul', + population: 21500000, + color: 'rgba(131, 167, 234, 1)', + legendFontColor: '#7F7F7F', + legendFontSize: 15 + }, + { + name: 'Toronto', + population: 2800000, + color: '#F00', + legendFontColor: '#7F7F7F', + legendFontSize: 15 + }, + { + name: 'Beijing', + population: 527612, + color: 'red', + legendFontColor: '#7F7F7F', + legendFontSize: 15 + }, + { + name: 'New York', + population: 8538000, + color: '#ffffff', + legendFontColor: '#7F7F7F', + legendFontSize: 15 + }, + { + name: 'Moscow', + population: 11920000, + color: 'rgb(0, 0, 255)', + legendFontColor: '#7F7F7F', + legendFontSize: 15 + } ] // Mock data object for Progress const progressChartData = [0.4, 0.6, 0.8] -export { data, contributionData, pieChartData, progressChartData } +const stackedBarGraphData = { + labels: ['Test1', 'Test2'], + legend: ['L1', 'L2', 'L3'], + data: [[60, 60, 60], [30, 30, 60]], + barColors: ['#dfe4ea', '#ced6e0', '#a4b0be'] +} + +export { + data, + contributionData, + pieChartData, + progressChartData, + stackedBarGraphData +} diff --git a/package.json b/package.json index 304315e2..4a56d1ea 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,8 @@ "react-test-renderer": "16.7.0", "xo": "^0.24.0" }, - "_main": "./node_modules/expo/AppEntry.js", - "main": "./index.js", + "main": "./node_modules/expo/AppEntry.js", + "_main": "./index.js", "scripts": { "start": "expo start", "eject": "expo eject", diff --git a/src/abstract-chart.js b/src/abstract-chart.js index 9a19f6c7..d7965e31 100644 --- a/src/abstract-chart.js +++ b/src/abstract-chart.js @@ -85,21 +85,23 @@ class AbstractChart extends Component { paddingRight, paddingTop, horizontalOffset = 0, - stackedBar = false, + stackedBar = false } = config const fontSize = 12 - var fac = 1; - if(stackedBar){ + let fac = 1 + if (stackedBar) { fac = 0.71 } + return labels.map((label, i) => { return ( { - const { data, width, height, paddingTop, paddingRight, border, colors } = config + const { + data, + width, + height, + paddingTop, + paddingRight, + border, + colors + } = config return data.map((x, i) => { - //for(g = 0; g - ); + const ret = [] + let h = 0 + let st = paddingTop + for (let z = 0; z < x.length; z++) { + h = (height - 55) * (x[z] / border) + const y = (height / 4) * 3 - h + st + const xC = + (paddingRight + + (i * (width - paddingRight)) / data.length + + barWidth / 2) * + 0.7 ret.push( - 15) ? (y+15) : (y+7)} - fontSize={12} - fill='#fff' - >{x[z]} - - ); - - st -= h; - } - return ret; + + ) + ret.push( + 15 ? y + 15 : y + 7} + fontSize={12} + fill="#fff" + > + {x[z]} + + ) + st -= h + } - }) + return ret + }) } renderLegend = config => { - const {legend, colors, width, height} = config; - return legend.map((x, i) =>{ - return ( - - - - - {x} - - - - ) - }) - + const {legend, colors, width, height} = config + return legend.map((x, i) => { + return ( + + + + {x} + + + ) + }) } render() { const paddingTop = 15 const paddingRight = 50 - const { width, height, style = {}, borders, data } = this.props - const { borderRadius = 0 } = style + const {width, height, style = {}, data} = this.props + const {borderRadius = 0} = style const config = { width, height } - var border = 0; - for(let i = 0; i pv + cv, 0); - if(actual > border){ - border = actual; - } + let border = 0 + for (let i = 0; i < data.data.length; i++) { + const actual = data.data[i].reduce((pv, cv) => pv + cv, 0) + if (actual > border) { + border = actual + } } return ( - + {this.renderDefs({ ...config, ...this.props.chartConfig @@ -119,50 +115,49 @@ class StackedBarChart extends AbstractChart { height={height} rx={borderRadius} ry={borderRadius} - fill="url(#backgroundGradient)"/> - - {this.renderHorizontalLines({ - ...config, - count: 4, - paddingTop - })} + fill="url(#backgroundGradient)" + /> - + {this.renderHorizontalLines({ + ...config, + count: 4, + paddingTop + })} - - {this.renderHorizontalLabels({ - ...config, - count: 4, - data: [0, border], - paddingTop, - paddingRight - })} + + {this.renderHorizontalLabels({ + ...config, + count: 4, + data: [0, border], + paddingTop, + paddingRight + })} - {this.renderVerticalLabels({ - ...config, - labels: data.labels, - paddingRight: paddingRight+28, - stackedBar: true, - paddingTop, - horizontalOffset: barWidth - })} + {this.renderVerticalLabels({ + ...config, + labels: data.labels, + paddingRight: paddingRight + 28, + stackedBar: true, + paddingTop, + horizontalOffset: barWidth + })} - {this.renderBars({ + {this.renderBars({ + ...config, + data: data.data, + border, + colors: this.props.data.barColors, + paddingTop, + paddingRight: paddingRight + 20 + })} + + {this.renderLegend({ ...config, - data: data.data, - border: border, - colors: this.props.chartConfig.barColors, - paddingTop, - paddingRight: (paddingRight+20) + legend: data.legend, + colors: this.props.data.barColors })} - - {this.renderLegend({ - ...config, - legend: data.legend, - colors: this.props.chartConfig.barColors, - })} )