Added dashed and dotted rules and reference lines to Bar and Line Charts

This commit is contained in:
abhinandan1234 2021-11-23 21:17:50 +05:30
parent 287518d677
commit d7281e681b
6 changed files with 668 additions and 253 deletions

39
App.js
View File

@ -187,8 +187,37 @@ const App = () => {
/> */}
{toggle ? (
<BarChart
// width={190}
data={data}
// horizontal
showReferenceLine1
referenceLine1Position={50}
referenceLine1Config={{
type: 'solid',
color: 'red',
thickness: 1,
dashWidth: 5,
dashGap: 13,
}}
showReferenceLine2
referenceLine2Position={10}
referenceLine2Config={{
type: 'solid',
// color: 'red',
thickness: 1,
dashWidth: 5,
dashGap: 13,
}}
showReferenceLine3
referenceLine3Position={20}
referenceLine3Config={{
type: 'solid',
color: 'red',
thickness: 1,
dashWidth: 5,
dashGap: 13,
}}
// showYAxisIndices
isAnimated
showGradient
cappedBars
@ -201,13 +230,19 @@ const App = () => {
capThickness={4}
barWidth={35}
gradientColor={'rgba(200, 100, 244,0.8)'}
frontColor={'rgba(219, 182, 249,0.2)'}
frontColor={'rgb(78, 0, 142)'}
rulesType="dashed"
rulesColor={'rgba(0,200,0,0.4)'}
rulesThickness={1}
dashWidth={12}
dashGap={2}
/>
) : (
<LineChart
// width={150}
data={data}
areaChart
initialSpacing={0}
initialSpacing={10}
curved
isAnimated
showGradient

View File

@ -68,7 +68,7 @@ So, all the three must be used together. Using any 1 or 2 of them may produce ab
### Axes and rules related props
| Prop | Type | Description | Default value |
| ---------------------- | ------------- | ---------------------------------------------------------------------- | ------------- |
| ---------------------- | ------------------- | ---------------------------------------------------------------------------------- | ---------------------- |
| xAxisColor | ColorValue | X axis color | black |
| xAxisThickness | number | X axis thickness | 1 |
| yAxisColor | ColorValue | Y axis color | black |
@ -81,6 +81,18 @@ So, all the three must be used together. Using any 1 or 2 of them may produce ab
| rulesColor | ColorValue | Color of the horizontal rules | lightgray |
| rulesThickness | number | Thickness of the horizontal rules | 1 |
| hideRules | Boolean | To hide the horizontal rules | false |
| rulesType | String | solid or dotted/dashed | solid |
| dashWidth | number | width of each dash | 4 |
| dashGap | number | gap between 2 dashes | 8 |
| showReferenceLine1 | Boolean | show reference line | false |
| referenceLine1Config | referenceConfigType | properties of reference line like thickness, color etc (described below the table) | \_ |
| referenceLine1Position | number | position of reference line | containerHeight / 2 |
| showReferenceLine2 | Boolean | show second reference line | false |
| referenceLine2Config | referenceConfigType | properties of reference line like thickness, color etc (described below the table) | \_ |
| referenceLine2Position | number | position of second reference line | 3\*containerHeight / 2 |
| showReferenceLine3 | Boolean | show third reference line | false |
| referenceLine3Config | referenceConfigType | properties of reference line like thickness, color etc (described below the table) | \_ |
| referenceLine3Position | number | position of third reference line | containerHeight / 3 |
| showVerticalLines | Boolean | To show vertical lines | false |
| verticalLinesColor | ColorValue | Color of the vertical lines | lightgray |
| verticallinesThickness | number | Thickness of the vertical lines | 1 |
@ -99,6 +111,19 @@ So, all the three must be used together. Using any 1 or 2 of them may produce ab
| hideOrigin | Boolean | To hide the y Axis label at origin (i.e. 0) | false |
| labelWidth | number | Width of the Label text appearing below the bar (under the X axis) | barWidth |
ReferenceConfigType has following properties-
```js
type referenceConfigType = {
thickness: number,
width: number,
color: ColorValue | String | any,
type: String,
dashWidth: number,
dashGap: number,
};
```
---
### Bar related props
@ -129,15 +154,11 @@ So, all the three must be used together. Using any 1 or 2 of them may produce ab
| animationDuration | number | Duration of the animations | 800 |
| animationEasing | Easing | Easing applied to the animation | Easing.ease |
**Alert!**\
While rendering an Animated Bar chart, y axis labels may not appear sometimes. This can be fixed using a key prop as shown -
```js
<BarChart
key={'xyz'}
data={data}
isAnimated/>
<BarChart key={'xyz'} data={data} isAnimated />
```
---

View File

@ -68,7 +68,7 @@ If you are adding showDataPoint to an item, you must set hideDataPoints prop to
### Axes and rules related props
| Prop | Type | Description | Default value |
| ---------------------- | ------------- | ---------------------------------------------------------------------- | ------------- |
| ---------------------- | ------------------- | ---------------------------------------------------------------------------------- | ---------------------- |
| xAxisColor | ColorValue | X axis color | black |
| xAxisThickness | number | X axis thickness | 1 |
| yAxisColor | ColorValue | Y axis color | black |
@ -81,6 +81,18 @@ If you are adding showDataPoint to an item, you must set hideDataPoints prop to
| rulesColor | ColorValue | Color of the horizontal rules | lightgray |
| rulesThickness | number | Thickness of the horizontal rules | 1 |
| hideRules | Boolean | To hide the horizontal rules | false |
| rulesType | String | solid or dotted/dashed | solid |
| dashWidth | number | width of each dash | 4 |
| dashGap | number | gap between 2 dashes | 8 |
| showReferenceLine1 | Boolean | show reference line | false |
| referenceLine1Config | referenceConfigType | properties of reference line like thickness, color etc (described below the table) | \_ |
| referenceLine1Position | number | position of reference line | containerHeight / 2 |
| showReferenceLine2 | Boolean | show second reference line | false |
| referenceLine2Config | referenceConfigType | properties of reference line like thickness, color etc (described below the table) | \_ |
| referenceLine2Position | number | position of second reference line | 3\*containerHeight / 2 |
| showReferenceLine3 | Boolean | show third reference line | false |
| referenceLine3Config | referenceConfigType | properties of reference line like thickness, color etc (described below the table) | \_ |
| referenceLine3Position | number | position of third reference line | containerHeight / 3 |
| showVerticalLines | Boolean | To show vertical lines | false |
| verticalLinesColor | ColorValue | Color of the vertical lines | lightgray |
| verticallinesThickness | number | Thickness of the vertical lines | 1 |
@ -98,6 +110,19 @@ If you are adding showDataPoint to an item, you must set hideDataPoints prop to
| rotateLabel | Boolean | To rotate the X axis labels (by 60deg) | false |
| hideOrigin | Boolean | To hide the y Axis label at origin (i.e. 0) | false |
ReferenceConfigType has following properties-
```js
type referenceConfigType = {
thickness: number,
width: number,
color: ColorValue | String | any,
type: String,
dashWidth: number,
dashGap: number,
};
```
---
### Line related props

View File

@ -3,6 +3,7 @@ import {View, FlatList, Animated, Easing, Text, ColorValue} from 'react-native';
import {styles} from './styles';
import RenderBars from './RenderBars';
import RenderStackBars from './RenderStackBars';
import Rule from '../Components/lineSvg';
type PropTypes = {
width?: number;
@ -41,6 +42,18 @@ type PropTypes = {
hideRules?: Boolean;
rulesColor?: ColorValue;
rulesThickness?: number;
rulesType?: String;
dashWidth?: number;
dashGap?: number;
showReferenceLine1?: Boolean;
referenceLine1Config?: referenceConfigType;
referenceLine1Position?: number;
showReferenceLine2?: Boolean;
referenceLine2Config?: referenceConfigType;
referenceLine2Position?: number;
showReferenceLine3?: Boolean;
referenceLine3Config?: referenceConfigType;
referenceLine3Position?: number;
showVerticalLines?: Boolean;
verticalLinesThickness?: number;
verticalLinesColor?: ColorValue;
@ -83,6 +96,14 @@ type PropTypes = {
labelWidth?: number;
yAxisLabelTexts?: Array<string>;
};
type referenceConfigType = {
thickness: number;
width: number;
color: ColorValue | String | any;
type: String;
dashWidth: number;
dashGap: number;
};
type sectionType = {
value: string;
};
@ -209,6 +230,78 @@ export const BarChart = (props: PropTypes) => {
const intactTopLabel = props.intactTopLabel || false;
const hideOrigin = props.hideOrigin || false;
const rulesType = props.rulesType || 'line';
const dashWidth = props.dashWidth === 0 ? 0 : props.dashWidth || 4;
const dashGap = props.dashGap === 0 ? 0 : props.dashGap || 8;
const defaultReferenceConfig = {
thickness: rulesThickness,
width: horizontal
? props.width || totalWidth
: (props.width || totalWidth) + 11,
color: 'black',
type: rulesType,
dashWidth: dashWidth,
dashGap: dashGap,
};
const showReferenceLine1 = props.showReferenceLine1 || false;
const referenceLine1Position =
props.referenceLine1Position === 0
? 0
: props.referenceLine1Position || containerHeight / 2;
const referenceLine1Config = props.referenceLine1Config
? {
thickness: props.referenceLine1Config.thickness || rulesThickness,
width: horizontal
? props.referenceLine1Config.width || props.width || totalWidth
: (props.referenceLine1Config.width || props.width || totalWidth) +
11,
color: props.referenceLine1Config.color || 'black',
type: props.referenceLine1Config.type || rulesType,
dashWidth: props.referenceLine1Config.dashWidth || dashWidth,
dashGap: props.referenceLine1Config.dashGap || dashGap,
}
: defaultReferenceConfig;
const showReferenceLine2 = props.showReferenceLine2 || false;
const referenceLine2Position =
props.referenceLine2Position === 0
? 0
: props.referenceLine2Position || (3 * containerHeight) / 2;
const referenceLine2Config = props.referenceLine2Config
? {
thickness: props.referenceLine2Config.thickness || rulesThickness,
width: horizontal
? props.referenceLine2Config.width || props.width || totalWidth
: (props.referenceLine2Config.width || props.width || totalWidth) +
11,
color: props.referenceLine2Config.color || 'black',
type: props.referenceLine2Config.type || rulesType,
dashWidth: props.referenceLine2Config.dashWidth || dashWidth,
dashGap: props.referenceLine2Config.dashGap || dashGap,
}
: defaultReferenceConfig;
const showReferenceLine3 = props.showReferenceLine3 || false;
const referenceLine3Position =
props.referenceLine3Position === 0
? 0
: props.referenceLine3Position || containerHeight / 3;
const referenceLine3Config = props.referenceLine3Config
? {
thickness: props.referenceLine3Config.thickness || rulesThickness,
width: horizontal
? props.referenceLine3Config.width || props.width || totalWidth
: (props.referenceLine3Config.width || props.width || totalWidth) +
11,
color: props.referenceLine3Config.color || 'black',
type: props.referenceLine3Config.type || rulesType,
dashWidth: props.referenceLine3Config.dashWidth || dashWidth,
dashGap: props.referenceLine3Config.dashGap || dashGap,
}
: defaultReferenceConfig;
horizSections.pop();
for (let i = 0; i <= noOfSections; i++) {
let value = maxValue - stepValue * i;
@ -264,7 +357,16 @@ export const BarChart = (props: PropTypes) => {
<>
{horizSections.map((sectionItems, index) => {
return (
<View key={index} style={[styles.horizBar, {width: totalWidth}]}>
<View
key={index}
style={[
styles.horizBar,
{
width: horizontal
? props.width || totalWidth
: props.width || totalWidth + 11,
},
]}>
<View
style={[
styles.leftLabel,
@ -325,16 +427,58 @@ export const BarChart = (props: PropTypes) => {
]}
/>
) : hideRules ? null : (
<View
style={[
styles.line,
{
height: rulesThickness,
backgroundColor: rulesColor,
},
]}
<Rule
config={{
thickness: rulesThickness,
color: rulesColor,
width: horizontal
? props.width || totalWidth
: (props.width || totalWidth) + 11,
dashWidth: dashWidth,
dashGap: dashGap,
type: rulesType,
}}
/>
)}
{index === 0 && showReferenceLine1 ? (
<View
style={{
position: 'absolute',
bottom:
(referenceLine1Position * containerHeight) / maxValue +
stepHeight / 2 -
referenceLine1Config.thickness / 2,
transform: [{translateY: containerHeight}],
}}>
<Rule config={referenceLine1Config} />
</View>
) : null}
{index === 0 && showReferenceLine2 ? (
<View
style={{
position: 'absolute',
bottom:
(referenceLine2Position * containerHeight) / maxValue +
stepHeight / 2 -
referenceLine2Config.thickness / 2,
transform: [{translateY: containerHeight}],
}}>
<Rule config={referenceLine2Config} />
</View>
) : null}
{index === 0 && showReferenceLine3 ? (
<View
style={{
position: 'absolute',
bottom:
(referenceLine3Position * containerHeight) / maxValue +
stepHeight / 2 -
referenceLine3Config.thickness / 2,
transform: [{translateY: containerHeight}],
}}>
<Rule config={referenceLine3Config} />
</View>
) : null}
{showYAxisIndices && index !== noOfSections ? (
<View
style={[
@ -380,16 +524,20 @@ export const BarChart = (props: PropTypes) => {
position: 'absolute',
bottom: stepHeight * -0.5 - 60 + xAxisThickness,
},
props.width && {width: props.width - 11},
horizontal && {width: totalWidth},
]}
scrollEnabled={!disableScroll}
contentContainerStyle={{
contentContainerStyle={[
{
height: containerHeight + 130,
width: totalWidth,
paddingLeft:
((data && data[0] && data[0].barWidth) || props.barWidth || 30) / 2,
((data && data[0] && data[0].barWidth) || props.barWidth || 30) /
2,
alignItems: 'flex-end',
}}
},
!props.width && {width: totalWidth},
]}
showsHorizontalScrollIndicator={showScrollIndicator}
horizontal
data={props.stackData || data}

View File

@ -0,0 +1,41 @@
import * as React from 'react';
import {ColorValue} from 'react-native';
import Svg, {G, Path} from 'react-native-svg';
type ruleProps = {
thickness: number;
width: number;
color: ColorValue | String | any;
type: String;
dashWidth: number;
dashGap: number;
};
type configType = {
config: ruleProps;
};
function Rule(props: configType) {
const {thickness, width, color, type, dashWidth, dashGap} = props.config;
if (type === 'solid') {
return (
<Svg height={thickness} width={width} {...props}>
<G fill="lightgray" stroke={color} strokeWidth={thickness}>
<Path d={`M0 ${thickness / 2}h${width}`} />
</G>
</Svg>
);
}
return (
<Svg height={thickness} width={width} {...props}>
<G fill="lightgray" stroke={color} strokeWidth={thickness}>
<Path
strokeDasharray={`${dashWidth},${dashGap}`}
d={`M0 ${thickness / 2}h${width}`}
/>
</G>
</Svg>
);
}
export default Rule;

View File

@ -17,6 +17,7 @@ import Svg, {
Text as CanvasText,
} from 'react-native-svg';
import {svgPath, bezierCommand} from '../utils';
import Rule from '../Components/lineSvg';
type propTypes = {
height?: number;
@ -43,6 +44,20 @@ type propTypes = {
hideRules?: Boolean;
rulesColor?: ColorValue;
rulesThickness?: number;
rulesType?: String;
dashWidth?: number;
dashGap?: number;
showReferenceLine1?: Boolean;
referenceLine1Config?: referenceConfigType;
referenceLine1Position?: number;
showReferenceLine2?: Boolean;
referenceLine2Config?: referenceConfigType;
referenceLine2Position?: number;
showReferenceLine3?: Boolean;
referenceLine3Config?: referenceConfigType;
referenceLine3Position?: number;
showVerticalLines?: Boolean;
verticalLinesThickness?: number;
verticalLinesColor?: ColorValue;
@ -137,6 +152,15 @@ type propTypes = {
textShiftX?: number;
textShiftY?: number;
yAxisLabelTexts?: Array<string>;
width?: number;
};
type referenceConfigType = {
thickness: number;
width: number;
color: ColorValue | String | any;
type: String;
dashWidth: number;
dashGap: number;
};
type itemType = {
value?: number;
@ -323,6 +347,70 @@ export const LineChart = (props: propTypes) => {
const showScrollIndicator = props.showScrollIndicator || false;
const hideOrigin = props.hideOrigin || false;
const rulesType = props.rulesType || 'line';
const dashWidth = props.dashWidth === 0 ? 0 : props.dashWidth || 4;
const dashGap = props.dashGap === 0 ? 0 : props.dashGap || 8;
const defaultReferenceConfig = {
thickness: rulesThickness,
width: (props.width || totalWidth) + 11,
color: 'black',
type: rulesType,
dashWidth: dashWidth,
dashGap: dashGap,
};
const showReferenceLine1 = props.showReferenceLine1 || false;
const referenceLine1Position =
props.referenceLine1Position === 0
? 0
: props.referenceLine1Position || containerHeight / 2;
const referenceLine1Config = props.referenceLine1Config
? {
thickness: props.referenceLine1Config.thickness || rulesThickness,
width:
(props.referenceLine1Config.width || props.width || totalWidth) + 11,
color: props.referenceLine1Config.color || 'black',
type: props.referenceLine1Config.type || rulesType,
dashWidth: props.referenceLine1Config.dashWidth || dashWidth,
dashGap: props.referenceLine1Config.dashGap || dashGap,
}
: defaultReferenceConfig;
const showReferenceLine2 = props.showReferenceLine2 || false;
const referenceLine2Position =
props.referenceLine2Position === 0
? 0
: props.referenceLine2Position || (3 * containerHeight) / 2;
const referenceLine2Config = props.referenceLine2Config
? {
thickness: props.referenceLine2Config.thickness || rulesThickness,
width:
(props.referenceLine2Config.width || props.width || totalWidth) + 11,
color: props.referenceLine2Config.color || 'black',
type: props.referenceLine2Config.type || rulesType,
dashWidth: props.referenceLine2Config.dashWidth || dashWidth,
dashGap: props.referenceLine2Config.dashGap || dashGap,
}
: defaultReferenceConfig;
const showReferenceLine3 = props.showReferenceLine3 || false;
const referenceLine3Position =
props.referenceLine3Position === 0
? 0
: props.referenceLine3Position || containerHeight / 3;
const referenceLine3Config = props.referenceLine3Config
? {
thickness: props.referenceLine3Config.thickness || rulesThickness,
width:
(props.referenceLine3Config.width || props.width || totalWidth) + 11,
color: props.referenceLine3Config.color || 'black',
type: props.referenceLine3Config.type || rulesType,
dashWidth: props.referenceLine3Config.dashWidth || dashWidth,
dashGap: props.referenceLine3Config.dashGap || dashGap,
}
: defaultReferenceConfig;
// console.log('data', data);
horizSections.pop();
for (let i = 0; i <= noOfSections; i++) {
@ -357,7 +445,8 @@ export const LineChart = (props: propTypes) => {
useEffect(() => {
let pp = '',
pp2 = '', pp3 = '';
pp2 = '',
pp3 = '';
if (!props.curved) {
for (let i = 0; i < data.length; i++) {
pp +=
@ -396,7 +485,8 @@ export const LineChart = (props: propTypes) => {
/*************************** For Area Charts *************************/
if (areaChart) {
let ppp = '',
ppp2 = '', ppp3 = '';
ppp2 = '',
ppp3 = '';
ppp =
'L' +
@ -478,7 +568,8 @@ export const LineChart = (props: propTypes) => {
/*************************************************************************************/
} else {
let p1Array = [],
p2Array = [], p3Array = [];
p2Array = [],
p3Array = [];
for (let i = 0; i < data.length; i++) {
p1Array.push([
initialSpacing - dataPointsWidth1 / 2 + spacing * i,
@ -619,14 +710,11 @@ export const LineChart = (props: propTypes) => {
bottom: 30,
zIndex: 10,
width: spacing,
// borderColor: 'red',
// borderWidth: 0.5,
// top: (value * containerHeight / maxValue) - 10,
left: initialSpacing + spacing * index - spacing / 2,
// opacity: appearingOpacity,
// backgroundColor: 'yellow',
left:
index === 0 && initialSpacing < 10
? initialSpacing + spacing * index - spacing / 2 + 8
: initialSpacing + spacing * index - spacing / 2,
justifyContent: 'center',
// alignSelf: 'center'
},
rotateLabel && {transform: [{rotate: '60deg'}]},
]}>
@ -648,14 +736,15 @@ export const LineChart = (props: propTypes) => {
style={[
{
height: rotateLabel ? 40 : 20,
// width: rotateLabel ? 30 : 100,
// backgroundColor: 'yellow',
position: 'absolute',
bottom: rotateLabel ? 10 : 30,
zIndex: 10,
width: spacing,
// top: (value * containerHeight / maxValue) - 10,
left: initialSpacing + spacing * index - spacing / 2,
left:
index === 0 && initialSpacing < 10
? initialSpacing + spacing * index - spacing / 2 + 8
: initialSpacing + spacing * index - spacing / 2,
opacity: appearingOpacity,
},
rotateLabel && {transform: [{rotate: '60deg'}]},
@ -747,7 +836,14 @@ export const LineChart = (props: propTypes) => {
{props.hideAxesAndRules !== true &&
horizSections.map((sectionItems, index) => {
return (
<View key={index} style={[styles.horizBar, { width: totalWidth }]}>
<View
key={index}
style={[
styles.horizBar,
{
width: props.width ? props.width + 15 : totalWidth,
},
]}>
<View
style={[
styles.leftLabel,
@ -800,16 +896,59 @@ export const LineChart = (props: propTypes) => {
]}
/>
) : hideRules ? null : (
<View
style={[
styles.line,
{
height: rulesThickness,
backgroundColor: rulesColor,
},
]}
<Rule
config={{
thickness: rulesThickness,
color: rulesColor,
width: (props.width || totalWidth) + 11,
dashWidth: dashWidth,
dashGap: dashGap,
type: rulesType,
}}
/>
)}
{index === 0 && showReferenceLine1 ? (
<View
style={{
position: 'absolute',
bottom:
(referenceLine1Position * containerHeight) /
maxValue +
stepHeight / 2 -
referenceLine1Config.thickness / 2,
transform: [{translateY: containerHeight}],
}}>
<Rule config={referenceLine1Config} />
</View>
) : null}
{index === 0 && showReferenceLine2 ? (
<View
style={{
position: 'absolute',
bottom:
(referenceLine2Position * containerHeight) /
maxValue +
stepHeight / 2 -
referenceLine2Config.thickness / 2,
transform: [{translateY: containerHeight}],
}}>
<Rule config={referenceLine2Config} />
</View>
) : null}
{index === 0 && showReferenceLine3 ? (
<View
style={{
position: 'absolute',
bottom:
(referenceLine3Position * containerHeight) /
maxValue +
stepHeight / 2 -
referenceLine3Config.thickness / 2,
transform: [{translateY: containerHeight}],
}}>
<Rule config={referenceLine3Config} />
</View>
) : null}
{showXAxisIndices && index !== noOfSections ? (
<View
style={{
@ -1242,19 +1381,25 @@ export const LineChart = (props: propTypes) => {
{/* {sectionsOverlay()} */}
<ScrollView
horizontal
contentContainerStyle={{
contentContainerStyle={[
{
height: containerHeight + 130,
width: totalWidth,
// backgroundColor: 'yellow'
}}
},
!props.width && {width: totalWidth},
]}
scrollEnabled={!disableScroll}
showsHorizontalScrollIndicator={showScrollIndicator}
style={{
style={[
{
marginLeft: yAxisLabelWidth + yAxisThickness,
position: 'absolute',
bottom: stepHeight * -0.5 - 60, //stepHeight * -0.5 + xAxisThickness,
paddingRight: 100,
}}>
},
props.width && {width: props.width + 10},
]}>
{showVerticalLines &&
data.map((item: itemType, index: number) => {
return (