Support for combined Line chart and Bar charts

This commit is contained in:
Abhinandan Kushwaha 2021-11-26 23:34:22 +05:30
parent 82e9341e72
commit bdf72d1213
7 changed files with 960 additions and 400 deletions

111
App.js
View File

@ -23,7 +23,7 @@ const App = () => {
const [toggle, setToggle] = useState(true);
const data = [
{value: 15, label: 'Jan', showVerticalLine: true},
{value: 15, label: 'Jan'},
{
value: 40,
label: 'Feb',
@ -172,7 +172,7 @@ const App = () => {
return (
<View
style={{
marginTop: 200,
marginTop: 100,
paddingVertical: 50,
}}>
{/* <LineChart data={ldata} /> */}
@ -187,40 +187,71 @@ const App = () => {
/> */}
{toggle ? (
<BarChart
isThreeD
key={'xyz'}
height={300}
maxValue={360}
showLine
initialSpacing={20}
// showVerticalLines
lineConfig={{
// isAnimated: true,
delay: 800,
color: 'green',
// hideDataPoints: true,
// showDataPoint: false,
// dataPointsRadius: 5,
dataPointsColor: 'purple',
dataPointsRadius: 4,
thickness: 2,
shiftY: 25,
curved: true,
}}
barWidth={32}
// width={190}
data={data}
data={[
{
value: 270,
label: 'Jan',
},
{value: 250, label: 'Feb'},
{value: 200, label: 'Mar'},
{
value: 150,
label: 'Apr',
showVerticalLine: true,
verticalLineColor: 'black',
},
{value: 200, label: 'May'},
{value: 250, label: 'Jun'},
{value: 270, label: 'Jul'},
]}
// 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,
}}
// showReferenceLine1
// referenceLine1Position={120}
// referenceLine1Config={{
// type: 'solid',
// color: 'rgba(200,0,0,0.6)',
// thickness: 1,
// }}
// showReferenceLine2
// referenceLine2Position={240}
// referenceLine2Config={{
// type: 'solid',
// color: 'rgba(0,0,0,0.6)',
// thickness: 1,
// }}
// showReferenceLine3
// referenceLine3Position={330}
// referenceLine3Config={{
// type: 'solid',
// color: 'rgba(0,0,200,0.6)',
// thickness: 1,
// }}
// showYAxisIndices
isAnimated
showGradient
cappedBars
// cappedBars
yAxisColor={'rgb(78, 0, 142)'}
xAxisColor={'rgb(78, 0, 142)'}
xAxisThickness={3}
@ -228,20 +259,20 @@ const App = () => {
yAxisTextStyle={{color: 'rgb(78, 0, 142)'}}
capColor={'rgb(78, 0, 142)'}
capThickness={4}
barWidth={35}
gradientColor={'rgba(200, 100, 244,0.8)'}
frontColor={'rgb(78, 0, 142)'}
rulesType="dashed"
rulesColor={'rgba(0,200,0,0.4)'}
rulesThickness={1}
dashWidth={12}
dashGap={2}
// barWidth={35}
frontColor={'rgba(200, 100, 244,0.2)'}
gradientColor={'rgba(78, 0, 142,1)'}
// rulesType="dashed"
// rulesColor={'rgba(0,200,0,0.5)'}
// rulesThickness={1}
// dashWidth={12}
// dashGap={2}
/>
) : (
<LineChart
// width={150}
data={data}
areaChart
// areaChart
initialSpacing={10}
curved
isAnimated

View File

@ -33,6 +33,7 @@ npm install react-native-gifted-charts react-native-linear-gradient
```
For Line and Area charts, add the react-native-svg package too -
```
npm install react-native-svg
```
@ -43,7 +44,6 @@ For Pie chart and Donut chart, these additional packages should be installed-
npm i react-native-canvas react-native-webview
```
For iOS-
```sh
@ -94,8 +94,7 @@ See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the
## Common issues
| Issue | Solution |
| ---- | ---- |
| [When the isAnimated is enabled the labels are not showing for Bar Charts](https://github.com/Abhinandan-Kushwaha/react-native-gifted-charts/issues/18) | [Comment by Abhinav](https://github.com/Abhinandan-Kushwaha/react-native-gifted-charts/issues/18#issuecomment-971662656) |
| ---------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| [BarChart - Value and section line don't match](https://github.com/Abhinandan-Kushwaha/react-native-gifted-charts/issues/35) | [Comment by the owner](https://github.com/Abhinandan-Kushwaha/react-native-gifted-charts/issues/35#issuecomment-972673281) |
## License

View File

@ -3,7 +3,7 @@
### Basic props
| Prop | Type | Description | Default value |
| ------------------- | -------------- | ------------------------------------------------------------------------------------ | ------------------- |
| ------------------- | -------------- | ----------------------------------------------------------------------------------------- | ------------------- |
| data | Array of items | An item object represents a bar in the bar chart. It is described in the next table. | \_ |
| width | number | Width of the Bar chart | width of the parent |
| height | number | Height of the Bar chart (excluding the bottom label) | 200 |
@ -15,6 +15,8 @@
| backgroundColor | ColorValue | Background color of the Bar chart | \_ |
| disableScroll | Boolean | To disable horizontal scroll | false |
| showScrollIndicator | Boolean | To show horizontal scroll indicator | false |
| showLine | Boolean | To show a Line chart over the Bar chart with the same data | false |
| lineConfig | lineConfigType | Properties of the Line chart shown over the Bar chart (lineConfigType) is described below | defaultLineConfig |
---
@ -35,6 +37,54 @@ So, all the three must be used together. Using any 1 or 2 of them may produce ab
---
**lineConfigType**
```js
type lineConfigType = {
curved?: Boolean,
isAnimated?: Boolean,
delay?: number,
thickness?: number,
color?: ColorValue,
hideDataPoints?: Boolean,
dataPointsShape?: String,
dataPointsWidth?: number,
dataPointsHeight?: number,
dataPointsColor?: ColorValue,
dataPointsRadius?: number,
textColor?: ColorValue,
textFontSize?: number,
textShiftX?: number,
textShiftY?: number,
shiftY?: number,
};
```
**defaultLineConfig**
```js
defaultLineConfig = {
curved: false,
isAnimated: false,
thickness: 1,
color: 'black',
hideDataPoints: false,
dataPointsShape: 'circular',
dataPointsWidth: 2,
dataPointsHeight: 2,
dataPointsColor: 'black',
dataPointsRadius: 3,
textColor: 'gray',
textFontSize: 10,
textShiftX: 0,
textShiftY: 0,
shiftY: 0,
delay: 0,
};
```
---
### Item description
| Key | Value type | Description |

View File

@ -1,9 +1,24 @@
import React, {useEffect} from 'react';
import {View, FlatList, Animated, Easing, Text, ColorValue} from 'react-native';
import React, {
Fragment,
useCallback,
useEffect,
useMemo,
useState,
} from 'react';
import {
View,
Animated,
Easing,
Text,
ColorValue,
ScrollView,
} from 'react-native';
import {styles} from './styles';
import RenderBars from './RenderBars';
import RenderStackBars from './RenderStackBars';
import Rule from '../Components/lineSvg';
import {bezierCommand, svgPath} from '../utils';
import Svg, {Circle, Path, Rect, Text as CanvasText} from 'react-native-svg';
type PropTypes = {
width?: number;
@ -19,7 +34,7 @@ type PropTypes = {
rotateLabel?: Boolean;
isAnimated?: Boolean;
animationDuration?: number;
animationEasing?: any;
// animationEasing?: any;
opacity?: number;
isThreeD?: Boolean;
xAxisThickness?: number;
@ -32,6 +47,8 @@ type PropTypes = {
initialSpacing?: number;
barWidth?: number;
sideWidth?: number;
showLine?: Boolean;
lineConfig?: lineConfigType;
cappedBars?: Boolean;
capThickness?: number;
@ -96,6 +113,24 @@ type PropTypes = {
labelWidth?: number;
yAxisLabelTexts?: Array<string>;
};
type lineConfigType = {
curved?: Boolean;
isAnimated?: Boolean;
delay?: number;
thickness?: number;
color?: ColorValue | String | any;
hideDataPoints?: Boolean;
dataPointsShape?: String;
dataPointsWidth?: number;
dataPointsHeight?: number;
dataPointsColor?: ColorValue | String | any;
dataPointsRadius?: number;
textColor?: ColorValue | String | any;
textFontSize?: number;
textShiftX?: number;
textShiftY?: number;
shiftY?: number;
};
type referenceConfigType = {
thickness: number;
width: number;
@ -127,11 +162,60 @@ type itemType = {
};
export const BarChart = (props: PropTypes) => {
const [points, setPoints] = useState('');
const showLine = props.showLine || false;
const defaultLineConfig = {
curved: false,
isAnimated: false,
thickness: 1,
color: 'black',
hideDataPoints: false,
dataPointsShape: 'circular',
dataPointsWidth: 2,
dataPointsHeight: 2,
dataPointsColor: 'black',
dataPointsRadius: 3,
textColor: 'gray',
textFontSize: 10,
textShiftX: 0,
textShiftY: 0,
shiftY: 0,
delay: 0,
};
const lineConfig = props.lineConfig
? {
curved: props.lineConfig.curved || defaultLineConfig.curved,
isAnimated: props.lineConfig.isAnimated || defaultLineConfig.isAnimated,
thickness: props.lineConfig.thickness || defaultLineConfig.thickness,
color: props.lineConfig.color || defaultLineConfig.color,
hideDataPoints:
props.lineConfig.hideDataPoints || defaultLineConfig.hideDataPoints,
dataPointsShape:
props.lineConfig.dataPointsShape || defaultLineConfig.dataPointsShape,
dataPointsHeight:
props.lineConfig.dataPointsHeight ||
defaultLineConfig.dataPointsHeight,
dataPointsWidth:
props.lineConfig.dataPointsWidth || defaultLineConfig.dataPointsWidth,
dataPointsColor:
props.lineConfig.dataPointsColor || defaultLineConfig.dataPointsColor,
dataPointsRadius:
props.lineConfig.dataPointsRadius ||
defaultLineConfig.dataPointsRadius,
textColor: props.lineConfig.textColor || defaultLineConfig.textColor,
textFontSize:
props.lineConfig.textFontSize || defaultLineConfig.textFontSize,
textShiftX: props.lineConfig.textShiftX || defaultLineConfig.textShiftX,
textShiftY: props.lineConfig.textShiftY || defaultLineConfig.textShiftY,
shiftY: props.lineConfig.shiftY || defaultLineConfig.shiftY,
delay: props.lineConfig.delay || defaultLineConfig.delay,
}
: defaultLineConfig;
const containerHeight = props.height || 200;
const noOfSections = props.noOfSections || 10;
const horizSections = [{value: '0'}];
const stepHeight = props.stepHeight || containerHeight / noOfSections;
const data = props.data || [];
const data = useMemo(() => props.data || [], [props.data]);
const spacing = props.spacing === 0 ? 0 : props.spacing ? props.spacing : 20;
const labelWidth = props.labelWidth || 0;
@ -184,7 +268,7 @@ export const BarChart = (props: PropTypes) => {
const rotateLabel = props.rotateLabel || false;
const isAnimated = props.isAnimated || false;
const animationDuration = props.animationDuration || 800;
const animationEasing = props.animationEasing || Easing.ease;
// const animationEasing = props.animationEasing || Easing.ease;
const opacity = props.opacity || 1;
const isThreeD = props.isThreeD || false;
@ -234,6 +318,108 @@ export const BarChart = (props: PropTypes) => {
const dashWidth = props.dashWidth === 0 ? 0 : props.dashWidth || 4;
const dashGap = props.dashGap === 0 ? 0 : props.dashGap || 8;
const heightValue = useMemo(() => new Animated.Value(0), []);
const opacValue = useMemo(() => new Animated.Value(0), []);
const widthValue = useMemo(() => new Animated.Value(0), []);
const labelsAppear = useCallback(() => {
opacValue.setValue(0);
Animated.timing(opacValue, {
toValue: 1,
duration: 500,
easing: Easing.ease,
useNativeDriver: false,
}).start();
}, [opacValue]);
// const moveBar = useCallback(() => {
// heightValue.setValue(0);
// Animated.timing(heightValue, {
// toValue: 1,
// duration: animationDuration,
// easing: animationEasing,
// useNativeDriver: false,
// }).start();
// }, [animationDuration, animationEasing, heightValue]);
const decreaseWidth = useCallback(() => {
widthValue.setValue(0);
Animated.timing(widthValue, {
toValue: 1,
duration: animationDuration,
easing: Easing.linear,
useNativeDriver: false,
}).start();
}, [animationDuration, widthValue]);
// console.log('olddata', oldData);
useEffect(() => {
if (showLine) {
let pp = '';
if (!lineConfig.curved) {
for (let i = 0; i < data.length; i++) {
const currentBarWidth =
(data && data[i] && data[i].barWidth) || props.barWidth || 30;
pp +=
'L' +
(yAxisLabelWidth +
6 -
(initialSpacing - currentBarWidth / 2) -
lineConfig.dataPointsWidth / 2 +
(currentBarWidth + spacing) * i) +
' ' +
(containerHeight -
lineConfig.shiftY +
10 -
(data[i].value * containerHeight) / maxValue) +
' ';
}
setPoints(pp.replace('L', 'M'));
} else {
let p1Array = [];
for (let i = 0; i < data.length; i++) {
const currentBarWidth =
(data && data[i] && data[i].barWidth) || props.barWidth || 30;
p1Array.push([
yAxisLabelWidth +
6 -
(initialSpacing - currentBarWidth / 2) -
lineConfig.dataPointsWidth / 2 +
(currentBarWidth + spacing) * i,
containerHeight -
lineConfig.shiftY +
10 -
(data[i].value * containerHeight) / maxValue,
]);
let xx = svgPath(p1Array, bezierCommand);
setPoints(xx);
}
}
if (lineConfig.isAnimated) {
setTimeout(() => decreaseWidth(), lineConfig.delay || 0);
}
}
// moveBar();
setTimeout(() => labelsAppear(), animationDuration);
}, [
animationDuration,
containerHeight,
data,
decreaseWidth,
initialSpacing,
labelsAppear,
lineConfig.curved,
lineConfig.dataPointsWidth,
lineConfig.shiftY,
lineConfig.isAnimated,
lineConfig.delay,
maxValue,
// moveBar,
props.barWidth,
showLine,
spacing,
yAxisLabelWidth,
]);
const defaultReferenceConfig = {
thickness: rulesThickness,
width: horizontal
@ -315,34 +501,6 @@ export const BarChart = (props: PropTypes) => {
});
}
const heightValue = new Animated.Value(0);
const opacValue = new Animated.Value(0);
const labelsAppear = () => {
opacValue.setValue(0);
Animated.timing(opacValue, {
toValue: 1,
duration: 500,
easing: Easing.ease,
useNativeDriver: false,
}).start();
};
const moveBar = () => {
heightValue.setValue(0);
Animated.timing(heightValue, {
toValue: 1,
duration: animationDuration,
easing: animationEasing,
useNativeDriver: false,
}).start();
};
// console.log('olddata', oldData);
useEffect(() => {
moveBar();
setTimeout(() => labelsAppear(), animationDuration);
}, []);
const animatedHeight = heightValue.interpolate({
inputRange: [0, 1],
outputRange: ['0%', '100%'],
@ -352,6 +510,11 @@ export const BarChart = (props: PropTypes) => {
outputRange: [0, 1],
});
const animatedWidth = widthValue.interpolate({
inputRange: [0, 1],
outputRange: [0, totalWidth],
});
const renderHorizSections = () => {
return (
<>
@ -506,6 +669,289 @@ export const BarChart = (props: PropTypes) => {
);
};
const renderSpecificVerticalLines = (dataForRender: any) => {
return dataForRender.map((item: any, index: number) => {
if (item.showVerticalLine) {
const currentBarWidth = item.barWidth || props.barWidth || 30;
return (
<Rect
x={
yAxisLabelWidth +
6 -
(item.verticalLineThickness || 1) / 2 -
1 -
(initialSpacing - currentBarWidth / 2) +
(currentBarWidth + spacing) * index
}
y={
containerHeight -
lineConfig.shiftY -
(item.value * containerHeight) / maxValue +
9
}
width={item.verticalLineThickness || 1}
height={
(item.value * containerHeight) / maxValue + lineConfig.shiftY
}
fill={item.verticalLineColor || 'lightgray'}
/>
);
}
return null;
});
};
const renderDataPoints = () => {
return data.map((item: any, index: number) => {
// console.log('comes in');
const currentBarWidth = item.barWidth || props.barWidth || 30;
if (lineConfig.dataPointsShape === 'rectangular') {
return (
<Fragment key={index}>
<Rect
x={
yAxisLabelWidth +
6 -
(initialSpacing - currentBarWidth / 2) -
lineConfig.dataPointsWidth +
(currentBarWidth + spacing) * index
}
y={
containerHeight -
lineConfig.shiftY -
lineConfig.dataPointsHeight / 2 +
10 -
(item.value * containerHeight) / maxValue
}
width={lineConfig.dataPointsWidth}
height={lineConfig.dataPointsHeight}
fill={lineConfig.dataPointsColor}
/>
{item.dataPointText && (
<CanvasText
fill={item.textColor || lineConfig.textColor}
fontSize={item.textFontSize || lineConfig.textFontSize}
x={
yAxisLabelWidth +
6 -
(initialSpacing - currentBarWidth / 2) -
lineConfig.dataPointsWidth +
(currentBarWidth + spacing) * index +
(item.textShiftX || lineConfig.textShiftX || 0)
}
y={
containerHeight -
lineConfig.shiftY -
lineConfig.dataPointsHeight / 2 +
10 -
(item.value * containerHeight) / maxValue +
(item.textShiftY || lineConfig.textShiftY || 0)
}>
{item.dataPointText}
</CanvasText>
)}
</Fragment>
);
}
return (
<Fragment key={index}>
<Circle
cx={
yAxisLabelWidth +
6 -
(initialSpacing - currentBarWidth / 2) -
lineConfig.dataPointsWidth / 2 +
(currentBarWidth + spacing) * index
}
cy={
containerHeight -
lineConfig.shiftY +
10 -
(item.value * containerHeight) / maxValue
}
r={lineConfig.dataPointsRadius}
fill={lineConfig.dataPointsColor}
/>
{item.dataPointText && (
<CanvasText
fill={item.textColor || lineConfig.textColor}
fontSize={item.textFontSize || lineConfig.textFontSize}
x={
yAxisLabelWidth +
6 -
(initialSpacing - currentBarWidth / 2) -
lineConfig.dataPointsWidth +
(currentBarWidth + spacing) * index +
(item.textShiftX || lineConfig.textShiftX || 0)
}
y={
containerHeight -
lineConfig.shiftY -
lineConfig.dataPointsHeight / 2 +
10 -
(item.value * containerHeight) / maxValue +
(item.textShiftY || lineConfig.textShiftY || 0)
}>
{item.dataPointText}
</CanvasText>
)}
</Fragment>
);
});
};
const renderSpecificDataPoints = dataForRender => {
return dataForRender.map((item: any, index: number) => {
const currentBarWidth = item.barWidth || props.barWidth || 30;
if (item.showDataPoint) {
if (item.dataPointShape === 'rectangular') {
return (
<Fragment key={index}>
<Rect
x={
initialSpacing -
(item.dataPointWidth || 2) / 2 -
1 +
(currentBarWidth + spacing) * index
}
y={
containerHeight -
lineConfig.shiftY -
(item.dataPointHeight || 2) / 2 +
10 -
(item.value * containerHeight) / maxValue
}
width={item.dataPointWidth || 2}
height={item.dataPointHeight || 2}
fill={item.dataPointColor || 'black'}
/>
{item.dataPointText && (
<CanvasText
fill={item.textColor || 'black'}
fontSize={item.textFontSize || 10}
x={
initialSpacing -
(item.dataPointWidth || 2) +
spacing * index +
(item.textShiftX || lineConfig.textShiftX || 0)
}
y={
containerHeight -
lineConfig.shiftY -
(item.dataPointHeight || 2) / 2 +
10 -
(item.value * containerHeight) / maxValue +
(item.textShiftY || lineConfig.textShiftY || 0)
}>
{item.dataPointText}
</CanvasText>
)}
</Fragment>
);
} else {
return (
<Fragment key={index}>
<Circle
cx={
initialSpacing -
(item.dataPointWidth || 2) / 2 +
spacing * index
}
cy={
containerHeight -
lineConfig.shiftY +
10 -
(item.value * containerHeight) / maxValue
}
r={item.dataPointRadius || 3}
fill={item.dataPointColor || 'black'}
/>
{item.dataPointText && (
<CanvasText
fill={item.textColor || 'black'}
fontSize={item.textFontSize || 10}
x={
initialSpacing -
(item.dataPointWidth || 2) +
spacing * index +
(item.textShiftX || lineConfig.textShiftX || 0)
}
y={
containerHeight -
lineConfig.shiftY -
(item.dataPointHeight || 2) / 2 +
10 -
(item.value * containerHeight) / maxValue +
(item.textShiftY || lineConfig.textShiftY || 0)
}>
{item.dataPointText}
</CanvasText>
)}
</Fragment>
);
}
}
return null;
});
};
const renderAnimatedLine = () => {
// console.log('animatedWidth is-------->', animatedWidth);
return (
<Animated.View
style={{
position: 'absolute',
height: containerHeight + 10,
bottom: 60, //stepHeight * -0.5 + xAxisThickness,
width: animatedWidth,
zIndex: -1,
// backgroundColor: 'wheat',
}}>
<Svg>
<Path
d={points}
fill="none"
stroke={lineConfig.color}
strokeWidth={lineConfig.thickness}
/>
{renderSpecificVerticalLines(data)}
{!lineConfig.hideDataPoints
? renderDataPoints()
: renderSpecificDataPoints(data)}
</Svg>
</Animated.View>
);
};
const renderLine = () => {
return (
<View
style={{
position: 'absolute',
height: containerHeight + 10,
bottom: 60, //stepHeight * -0.5 + xAxisThickness,
width: totalWidth,
zIndex: -1,
// backgroundColor: 'rgba(200,150,150,0.1)'
}}>
<Svg>
<Path
d={points}
fill="none"
stroke={lineConfig.color}
strokeWidth={lineConfig.thickness}
/>
{renderSpecificVerticalLines(data)}
{!lineConfig.hideDataPoints
? renderDataPoints()
: renderSpecificDataPoints(data)}
</Svg>
</View>
);
};
return (
<View
style={[
@ -517,10 +963,10 @@ export const BarChart = (props: PropTypes) => {
horizontal && {transform: [{rotate: '90deg'}, {translateY: -15}]},
]}>
{props.hideAxesAndRules !== true && renderHorizSections()}
<FlatList
<ScrollView
style={[
{
marginLeft: initialSpacing + 6,
marginLeft: 36,
position: 'absolute',
bottom: stepHeight * -0.5 - 60 + xAxisThickness,
},
@ -530,24 +976,28 @@ export const BarChart = (props: PropTypes) => {
scrollEnabled={!disableScroll}
contentContainerStyle={[
{
// backgroundColor: 'yellow',
height: containerHeight + 130,
paddingLeft:
((data && data[0] && data[0].barWidth) || props.barWidth || 30) /
2,
paddingLeft: initialSpacing,
alignItems: 'flex-end',
},
!props.width && {width: totalWidth},
]}
showsHorizontalScrollIndicator={showScrollIndicator}
horizontal
data={props.stackData || data}
keyExtractor={(item, index) => index.toString()}
renderItem={({item, index}) => {
// console.log('index--->', index);
// console.log('itemhere--->', item);
if (props.stackData) {
// data={props.stackData || data}
keyExtractor={(item, index) => index.toString()}>
<Fragment>
{showLine
? lineConfig.isAnimated
? renderAnimatedLine()
: renderLine()
: null}
{props.stackData
? props.stackData.map((item, index) => {
return (
<RenderStackBars
key={index}
item={item}
index={index}
containerHeight={containerHeight}
@ -570,9 +1020,10 @@ export const BarChart = (props: PropTypes) => {
barBorderRadius={props.barBorderRadius}
/>
);
}
return (
})
: data.map((item, index) => (
<RenderBars
key={index}
item={item}
index={index}
containerHeight={containerHeight}
@ -615,9 +1066,9 @@ export const BarChart = (props: PropTypes) => {
intactTopLabel={intactTopLabel}
barBorderRadius={props.barBorderRadius}
/>
);
}}
/>
))}
</Fragment>
</ScrollView>
</View>
);
};

View File

@ -1,4 +1,4 @@
import { StyleSheet } from 'react-native';
import {StyleSheet} from 'react-native';
export const styles = StyleSheet.create({
container: {

View File

@ -1,4 +1,10 @@
import React, {Fragment, useEffect, useState} from 'react';
import React, {
Fragment,
useCallback,
useEffect,
useMemo,
useState,
} from 'react';
import {
View,
ScrollView,
@ -197,113 +203,64 @@ export const LineChart = (props: propTypes) => {
const [fillPoints3, setFillPoints3] = useState('');
const containerHeight = props.height || 200;
const noOfSections = props.noOfSections || 10;
const data = props.data || [];
const spacing = props.spacing === 0 ? 0 : props.spacing || 60;
const data = useMemo(() => props.data || [], [props.data]);
const data2 = useMemo(() => props.data2 || [], [props.data2]);
const data3 = useMemo(() => props.data3 || [], [props.data3]);
let totalWidth = spacing;
let maxItem = 0;
data.forEach((item: itemType) => {
if (item.value > maxItem) {
maxItem = item.value;
}
totalWidth += spacing;
});
if (props.showFractionalValues || props.roundToDigits) {
maxItem *= 10 * (props.roundToDigits || 1);
maxItem = maxItem + (10 - (maxItem % 10));
maxItem /= 10 * (props.roundToDigits || 1);
maxItem = parseFloat(maxItem.toFixed(props.roundToDigits || 1));
} else {
maxItem = maxItem + (10 - (maxItem % 10));
}
const opacValue = useMemo(() => new Animated.Value(0), []);
const widthValue = useMemo(() => new Animated.Value(0), []);
const widthValue2 = useMemo(() => new Animated.Value(0), []);
const widthValue3 = useMemo(() => new Animated.Value(0), []);
const maxValue = props.maxValue || maxItem;
const horizSections = [{value: '0'}];
const stepHeight = props.stepHeight || containerHeight / noOfSections;
const stepValue = props.stepValue || maxValue / noOfSections;
const initialSpacing =
props.initialSpacing === 0 ? 0 : props.initialSpacing || 40;
const data2 = props.data2 || [];
const data3 = props.data3 || [];
const thickness = props.thickness || 2;
const thickness1 = props.thickness1;
const thickness2 = props.thickness2;
const thickness3 = props.thickness3;
const rotateLabel = props.rotateLabel || false;
const isAnimated = props.isAnimated || false;
const animationDuration = props.animationDuration || 800;
const animateTogether = props.animateTogether || false;
const hideDataPoints1 =
props.hideDataPoints || props.hideDataPoints1 || false;
const hideDataPoints2 =
props.hideDataPoints || props.hideDataPoints2 || false;
const hideDataPoints3 =
props.hideDataPoints || props.hideDataPoints3 || false;
const color1 = props.color1 || props.color || 'black';
const color2 = props.color2 || props.color || 'black';
const color3 = props.color3 || props.color || 'black';
const labelsAppear = useCallback(() => {
opacValue.setValue(0);
Animated.timing(opacValue, {
toValue: 1,
duration: 500,
easing: Easing.ease,
useNativeDriver: false,
}).start();
}, [opacValue]);
const startFillColor1 =
props.startFillColor1 || props.startFillColor || 'gray';
const endFillColor1 = props.endFillColor1 || props.endFillColor || 'white';
const startOpacity1 = props.startOpacity1 || props.startOpacity || 1;
const endOpacity1 = props.endOpacity1 || props.endOpacity || 1;
const appearingOpacity = opacValue.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
});
const startFillColor2 =
props.startFillColor2 || props.startFillColor || 'gray';
const endFillColor2 = props.endFillColor2 || props.endFillColor || 'white';
const startOpacity2 = props.startOpacity2 || props.startOpacity || 1;
const endOpacity2 = props.endOpacity2 || props.endOpacity || 1;
const decreaseWidth = useCallback(() => {
widthValue.setValue(0);
Animated.timing(widthValue, {
toValue: 1,
duration: animationDuration,
easing: Easing.linear,
useNativeDriver: false,
}).start();
}, [animationDuration, widthValue]);
const startFillColor3 =
props.startFillColor3 || props.startFillColor || 'gray';
const endFillColor3 = props.endFillColor3 || props.endFillColor || 'white';
const startOpacity3 = props.startOpacity3 || props.startOpacity || 1;
const endOpacity3 = props.endOpacity3 || props.endOpacity || 1;
const decreaseWidth2 = useCallback(() => {
widthValue2.setValue(0);
Animated.timing(widthValue2, {
toValue: 1,
duration: animationDuration,
easing: Easing.linear,
useNativeDriver: false,
}).start();
}, [animationDuration, widthValue2]);
const rulesThickness =
props.rulesThickness === 0 ? 0 : props.rulesThickness || 1;
const rulesColor = props.rulesColor || 'lightgray';
const verticalLinesThickness =
props.verticalLinesThickness === 0 ? 0 : props.verticalLinesThickness || 1;
const verticalLinesColor = props.verticalLinesColor || 'lightgray';
const verticalLinesZIndex = props.verticalLinesZIndex || -1;
const decreaseWidth3 = useCallback(() => {
widthValue3.setValue(0);
Animated.timing(widthValue3, {
toValue: 1,
duration: animationDuration,
easing: Easing.linear,
useNativeDriver: false,
}).start();
}, [animationDuration, widthValue3]);
const gradientDirection = props.gradientDirection || 'vertical';
// const animationEasing = props.animationEasing || Easing.ease
// const opacity = props.opacity || 1;
const opacValue = new Animated.Value(0);
const widthValue = new Animated.Value(0);
const widthValue2 = new Animated.Value(0);
const widthValue3 = new Animated.Value(0);
const xAxisThickness = props.xAxisThickness || 1;
const xAxisColor = props.xAxisColor || 'black';
const hideRules = props.hideRules || false;
const areaChart = props.areaChart || false;
const showVerticalLines = props.showVerticalLines || false;
const showYAxisIndices = props.showYAxisIndices || false;
const showXAxisIndices = props.showXAxisIndices || false;
const yAxisIndicesHeight = props.yAxisIndicesHeight || 4;
const xAxisIndicesHeight = props.xAxisIndicesHeight || 2;
const yAxisIndicesWidth = props.yAxisIndicesWidth || 2;
const xAxisIndicesWidth = props.xAxisIndicesWidth || 4;
const xAxisIndicesColor = props.xAxisIndicesColor || 'black';
const yAxisIndicesColor = props.yAxisIndicesColor || 'black';
const yAxisThickness = props.yAxisThickness || 1;
const yAxisColor = props.yAxisColor || 'black';
const yAxisTextStyle = props.yAxisTextStyle;
const showFractionalValues = props.showFractionalValues || false;
const yAxisLabelWidth = props.yAxisLabelWidth || 35;
const hideYAxisText = props.hideYAxisText || false;
const dataPointsHeight1 =
props.dataPointsHeight1 || props.dataPointsHeight || 2;
const dataPointsWidth1 = props.dataPointsWidth1 || props.dataPointsWidth || 2;
@ -340,90 +297,25 @@ export const LineChart = (props: propTypes) => {
const textColor1 = props.textColor1 || props.textColor || 'gray';
const textColor2 = props.textColor2 || props.textColor || 'gray';
const textColor3 = props.textColor3 || props.textColor || 'gray';
const initialSpacing =
props.initialSpacing === 0 ? 0 : props.initialSpacing || 40;
const thickness = props.thickness || 2;
const backgroundColor = props.backgroundColor || 'transparent';
const spacing = props.spacing === 0 ? 0 : props.spacing || 60;
const disableScroll = props.disableScroll || false;
const showScrollIndicator = props.showScrollIndicator || false;
const hideOrigin = props.hideOrigin || false;
const xAxisThickness = props.xAxisThickness || 1;
const xAxisColor = props.xAxisColor || 'black';
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,
let totalWidth = spacing;
let maxItem = 0;
data.forEach((item: itemType) => {
if (item.value > maxItem) {
maxItem = item.value;
}
: 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++) {
let value = maxValue - stepValue * i;
if (props.showFractionalValues || props.roundToDigits) {
value = parseFloat(value.toFixed(props.roundToDigits || 1));
}
horizSections.push({
value: props.yAxisLabelTexts
? props.yAxisLabelTexts[noOfSections - i] ?? value.toString()
: value.toString(),
totalWidth += spacing;
});
}
const maxValue = props.maxValue || maxItem;
useEffect(() => {
// console.log('comes here............')
@ -441,7 +333,14 @@ export const LineChart = (props: propTypes) => {
},
animateTogether ? 0 : animationDuration * 2,
);
});
}, [
animateTogether,
animationDuration,
decreaseWidth,
decreaseWidth2,
decreaseWidth3,
labelsAppear,
]);
useEffect(() => {
let pp = '',
@ -699,7 +598,182 @@ export const LineChart = (props: propTypes) => {
/*************************************************************************************/
}
}, [data]);
}, [
areaChart,
containerHeight,
data,
data2,
data3,
dataPointsWidth1,
dataPointsWidth2,
dataPointsWidth3,
initialSpacing,
maxValue,
props.curved,
spacing,
xAxisThickness,
]);
if (props.showFractionalValues || props.roundToDigits) {
maxItem *= 10 * (props.roundToDigits || 1);
maxItem = maxItem + (10 - (maxItem % 10));
maxItem /= 10 * (props.roundToDigits || 1);
maxItem = parseFloat(maxItem.toFixed(props.roundToDigits || 1));
} else {
maxItem = maxItem + (10 - (maxItem % 10));
}
const horizSections = [{value: '0'}];
const stepHeight = props.stepHeight || containerHeight / noOfSections;
const stepValue = props.stepValue || maxValue / noOfSections;
const thickness1 = props.thickness1;
const thickness2 = props.thickness2;
const thickness3 = props.thickness3;
const rotateLabel = props.rotateLabel || false;
const isAnimated = props.isAnimated || false;
const hideDataPoints1 =
props.hideDataPoints || props.hideDataPoints1 || false;
const hideDataPoints2 =
props.hideDataPoints || props.hideDataPoints2 || false;
const hideDataPoints3 =
props.hideDataPoints || props.hideDataPoints3 || false;
const color1 = props.color1 || props.color || 'black';
const color2 = props.color2 || props.color || 'black';
const color3 = props.color3 || props.color || 'black';
const startFillColor1 =
props.startFillColor1 || props.startFillColor || 'gray';
const endFillColor1 = props.endFillColor1 || props.endFillColor || 'white';
const startOpacity1 = props.startOpacity1 || props.startOpacity || 1;
const endOpacity1 = props.endOpacity1 || props.endOpacity || 1;
const startFillColor2 =
props.startFillColor2 || props.startFillColor || 'gray';
const endFillColor2 = props.endFillColor2 || props.endFillColor || 'white';
const startOpacity2 = props.startOpacity2 || props.startOpacity || 1;
const endOpacity2 = props.endOpacity2 || props.endOpacity || 1;
const startFillColor3 =
props.startFillColor3 || props.startFillColor || 'gray';
const endFillColor3 = props.endFillColor3 || props.endFillColor || 'white';
const startOpacity3 = props.startOpacity3 || props.startOpacity || 1;
const endOpacity3 = props.endOpacity3 || props.endOpacity || 1;
const rulesThickness =
props.rulesThickness === 0 ? 0 : props.rulesThickness || 1;
const rulesColor = props.rulesColor || 'lightgray';
const verticalLinesThickness =
props.verticalLinesThickness === 0 ? 0 : props.verticalLinesThickness || 1;
const verticalLinesColor = props.verticalLinesColor || 'lightgray';
const verticalLinesZIndex = props.verticalLinesZIndex || -1;
const gradientDirection = props.gradientDirection || 'vertical';
// const animationEasing = props.animationEasing || Easing.ease
// const opacity = props.opacity || 1;
const hideRules = props.hideRules || false;
const showVerticalLines = props.showVerticalLines || false;
const showYAxisIndices = props.showYAxisIndices || false;
const showXAxisIndices = props.showXAxisIndices || false;
const yAxisIndicesHeight = props.yAxisIndicesHeight || 4;
const xAxisIndicesHeight = props.xAxisIndicesHeight || 2;
const yAxisIndicesWidth = props.yAxisIndicesWidth || 2;
const xAxisIndicesWidth = props.xAxisIndicesWidth || 4;
const xAxisIndicesColor = props.xAxisIndicesColor || 'black';
const yAxisIndicesColor = props.yAxisIndicesColor || 'black';
const yAxisThickness = props.yAxisThickness || 1;
const yAxisColor = props.yAxisColor || 'black';
const yAxisTextStyle = props.yAxisTextStyle;
const showFractionalValues = props.showFractionalValues || false;
const yAxisLabelWidth = props.yAxisLabelWidth || 35;
const hideYAxisText = props.hideYAxisText || false;
const backgroundColor = props.backgroundColor || 'transparent';
const disableScroll = props.disableScroll || false;
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++) {
let value = maxValue - stepValue * i;
if (props.showFractionalValues || props.roundToDigits) {
value = parseFloat(value.toFixed(props.roundToDigits || 1));
}
horizSections.push({
value: props.yAxisLabelTexts
? props.yAxisLabelTexts[noOfSections - i] ?? value.toString()
: value.toString(),
});
}
const renderLabel = (index: number, label: String, labelTextStyle: any) => {
return (
@ -756,51 +830,6 @@ export const LineChart = (props: propTypes) => {
);
};
const labelsAppear = () => {
opacValue.setValue(0);
Animated.timing(opacValue, {
toValue: 1,
duration: 500,
easing: Easing.ease,
useNativeDriver: false,
}).start();
};
const appearingOpacity = opacValue.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
});
const decreaseWidth = () => {
widthValue.setValue(0);
Animated.timing(widthValue, {
toValue: 1,
duration: animationDuration,
easing: Easing.linear,
useNativeDriver: false,
}).start();
};
const decreaseWidth2 = () => {
widthValue2.setValue(0);
Animated.timing(widthValue2, {
toValue: 1,
duration: animationDuration,
easing: Easing.linear,
useNativeDriver: false,
}).start();
};
const decreaseWidth3 = () => {
widthValue3.setValue(0);
Animated.timing(widthValue3, {
toValue: 1,
duration: animationDuration,
easing: Easing.linear,
useNativeDriver: false,
}).start();
};
const animatedWidth = widthValue.interpolate({
inputRange: [0, 1],
outputRange: [0, totalWidth],

View File

@ -200,7 +200,7 @@ export const PieChart = (props: propTypes) => {
ctx.moveTo(
radius + initialValue + shiftX,
radius + initialValue + shiftY,
)
);
ctx.lineTo(
radius + initialValue + shiftX,
radius + initialValue + shiftY,
@ -238,7 +238,7 @@ export const PieChart = (props: propTypes) => {
ctx.moveTo(
radius + initialValue + shiftX,
radius + initialValue + shiftY,
)
);
ctx.lineTo(
radius + initialValue + shiftX,
radius + initialValue + shiftY,