Added smooth transition animations for change in data iin Line and Area Charts

This commit is contained in:
Abhinandan Kushwaha 2022-01-12 16:52:27 +05:30
parent bb4195e7fa
commit 937872b1b9
5 changed files with 599 additions and 95 deletions

497
App.js
View File

@ -1,4 +1,4 @@
import React, {useState} from 'react';
import React, {useEffect, useState} from 'react';
import {TouchableOpacity} from 'react-native';
import {Alert} from 'react-native';
import {View, Text, StyleSheet} from 'react-native';
@ -6,15 +6,43 @@ import {BarChart, LineChart} from './src';
const App = () => {
const [toggle, setToggle] = useState(true);
useEffect(() => {
setTimeout(() => {
setCurrentData(latestData5);
}, 1100 + 100 + 310);
setTimeout(() => {
setCurrentData(latestData2);
}, 1100 + 300 + 620);
setTimeout(() => {
setCurrentData(latestData5);
}, 1100 + 500 + 930);
setTimeout(() => {
setCurrentData(latestData3);
}, 1100 + 1000 + 1240);
setTimeout(() => {
setCurrentData(latestData4);
}, 1100 + 1500 + 1550);
setTimeout(() => {
setCurrentData(latestData5);
}, 6000);
setTimeout(() => {
setCurrentData(latestData);
}, 7000);
}, []);
const dPoint = () => {
return (
<View
style={{
width: 20,
height: 20,
width: 14,
height: 14,
backgroundColor: 'white',
borderWidth: 4,
borderRadius: 10,
borderWidth: 3,
borderRadius: 7,
borderColor: '#07BAD1',
}}
/>
@ -29,24 +57,24 @@ const App = () => {
};
const latestData = [
{
value: 100,
value: 600 - 100,
labelComponent: () => lcomp('22 Nov'),
customDataPoint: dPoint,
},
{
value: 140,
value: 600 - 120,
hideDataPoint: true,
},
{
value: 250,
value: 600 - 210,
customDataPoint: dPoint,
},
{
value: 290,
value: 600 - 250,
hideDataPoint: true,
},
{
value: 410,
value: 600 - 320,
labelComponent: () => lcomp('24 Nov'),
customDataPoint: dPoint,
showStrip: true,
@ -69,32 +97,378 @@ const App = () => {
dataPointLabelShiftX: -14,
},
{
value: 440,
value: 600 - 310,
hideDataPoint: true,
},
{
value: 300,
value: 600 - 270,
customDataPoint: dPoint,
},
{
value: 280,
value: 600 - 240,
hideDataPoint: true,
},
{
value: 180,
value: 600 - 130,
labelComponent: () => lcomp('26 Nov'),
customDataPoint: dPoint,
},
{
value: 150,
value: 600 - 120,
hideDataPoint: true,
},
{
value: 150,
value: 600 - 100,
customDataPoint: dPoint,
},
{
value: 600 - 210,
hideDataPoint: true,
},
{
value: 600 - 270,
labelComponent: () => lcomp('28 Nov'),
customDataPoint: dPoint,
},
{
value: 600 - 240,
hideDataPoint: true,
},
{
value: 600 - 120,
hideDataPoint: true,
},
{
value: 600 - 100,
customDataPoint: dPoint,
},
{
value: 600 - 210,
labelComponent: () => lcomp('28 Nov'),
customDataPoint: dPoint,
},
{
value: 600 - 20,
hideDataPoint: true,
},
{
value: 600 - 100,
customDataPoint: dPoint,
},
];
const latestData2 = [
{
value: 400 - 100,
labelComponent: () => lcomp('22 Nov'),
customDataPoint: dPoint,
},
{
value: 400 - 120,
hideDataPoint: true,
},
{
value: 400 - 210,
customDataPoint: dPoint,
},
{
value: 400 - 250,
hideDataPoint: true,
},
{
value: 400 - 320,
labelComponent: () => lcomp('24 Nov'),
customDataPoint: dPoint,
showStrip: true,
stripHeight: 190,
stripColor: 'black',
dataPointLabelComponent: () => {
return (
<View
style={{
backgroundColor: 'black',
paddingHorizontal: 8,
paddingVertical: 5,
borderRadius: 4,
}}>
<Text style={{color: 'white'}}>410</Text>
</View>
);
},
dataPointLabelShiftY: -70,
dataPointLabelShiftX: -14,
},
{
value: 400 - 310,
hideDataPoint: true,
},
{
value: 400 - 270,
customDataPoint: dPoint,
},
{
value: 400 - 240,
hideDataPoint: true,
},
{
value: 400 - 130,
labelComponent: () => lcomp('26 Nov'),
customDataPoint: dPoint,
},
{
value: 400 - 120,
hideDataPoint: true,
},
{
value: 400 - 100,
customDataPoint: dPoint,
},
{
value: 400 - 210,
hideDataPoint: true,
},
{
value: 400 - 270,
labelComponent: () => lcomp('28 Nov'),
customDataPoint: dPoint,
},
{
value: 400 - 240,
hideDataPoint: true,
},
{
value: 400 - 120,
hideDataPoint: true,
},
{
value: 400 - 100,
customDataPoint: dPoint,
},
{
value: 400 - 210,
labelComponent: () => lcomp('28 Nov'),
customDataPoint: dPoint,
},
{
value: 400 - 20,
hideDataPoint: true,
},
{
value: 400 - 100,
customDataPoint: dPoint,
},
];
const latestData3 = [
{
value: 600 - 170,
labelComponent: () => lcomp('22 Nov'),
customDataPoint: dPoint,
},
{
value: 600 - 60,
hideDataPoint: true,
},
{
value: 600 - 290,
customDataPoint: dPoint,
},
{
value: 600 - 120,
hideDataPoint: true,
},
{
value: 600 - 390,
labelComponent: () => lcomp('24 Nov'),
customDataPoint: dPoint,
showStrip: true,
stripHeight: 190,
stripColor: 'black',
dataPointLabelComponent: () => {
return (
<View
style={{
backgroundColor: 'black',
paddingHorizontal: 8,
paddingVertical: 5,
borderRadius: 4,
}}>
<Text style={{color: 'white'}}>410</Text>
</View>
);
},
dataPointLabelShiftY: -70,
dataPointLabelShiftX: -14,
},
{
value: 600 - 210,
hideDataPoint: true,
},
{
value: 600 - 370,
customDataPoint: dPoint,
},
{
value: 600 - 140,
hideDataPoint: true,
},
{
value: 600 - 330,
labelComponent: () => lcomp('26 Nov'),
customDataPoint: dPoint,
},
{
value: 600 - 50,
hideDataPoint: true,
},
{
value: 600 - 200,
customDataPoint: dPoint,
},
{
value: 600 - 110,
hideDataPoint: true,
},
{
value: 600 - 370,
labelComponent: () => lcomp('28 Nov'),
customDataPoint: dPoint,
},
{
value: 600 - 140,
hideDataPoint: true,
},
{
value: 600 - 320,
hideDataPoint: true,
},
{
value: 600 - 20,
customDataPoint: dPoint,
},
{
value: 600 - 310,
labelComponent: () => lcomp('28 Nov'),
customDataPoint: dPoint,
},
{
value: 600 - 120,
hideDataPoint: true,
},
{
value: 600 - 100,
customDataPoint: dPoint,
},
];
const latestData4 = [
{
value: 300 - 170,
labelComponent: () => lcomp('22 Nov'),
customDataPoint: dPoint,
},
{
value: 300 - 60,
hideDataPoint: true,
},
{
value: 300 - 290,
customDataPoint: dPoint,
},
{
value: 300 - 120,
hideDataPoint: true,
},
{
value: 300 - 390,
labelComponent: () => lcomp('24 Nov'),
customDataPoint: dPoint,
showStrip: true,
stripHeight: 190,
stripColor: 'black',
dataPointLabelComponent: () => {
return (
<View
style={{
backgroundColor: 'black',
paddingHorizontal: 8,
paddingVertical: 5,
borderRadius: 4,
}}>
<Text style={{color: 'white'}}>410</Text>
</View>
);
},
dataPointLabelShiftY: -70,
dataPointLabelShiftX: -14,
},
{
value: 300 - 210,
hideDataPoint: true,
},
{
value: 300 - 370,
customDataPoint: dPoint,
},
{
value: 300 - 140,
hideDataPoint: true,
},
{
value: 300 - 330,
labelComponent: () => lcomp('26 Nov'),
customDataPoint: dPoint,
},
{
value: 300 - 50,
hideDataPoint: true,
},
{
value: 300 - 200,
customDataPoint: dPoint,
},
{
value: 300 - 110,
hideDataPoint: true,
},
{
value: 300 - 370,
labelComponent: () => lcomp('28 Nov'),
customDataPoint: dPoint,
},
{
value: 300 - 140,
hideDataPoint: true,
},
{
value: 300 - 320,
hideDataPoint: true,
},
{
value: 300 - 20,
customDataPoint: dPoint,
},
{
value: 300 - 310,
labelComponent: () => lcomp('28 Nov'),
customDataPoint: dPoint,
},
{
value: 300 - 120,
hideDataPoint: true,
},
{
value: 300 - 100,
customDataPoint: dPoint,
},
];
const latestData5 = [];
for (let i = 0; i < latestData.length; i++) {
latestData5[i] = {...latestData, value: 300};
}
const [currentData, setCurrentData] = useState(latestData);
const customLabel = val => {
return (
<View
@ -154,35 +528,68 @@ const App = () => {
]);
return (
<View
style={{
marginTop: 100,
paddingVertical: 50,
backgroundColor: '#414141',
}}>
<LineChart
thickness={6}
color="#07BAD1"
maxValue={600}
noOfSections={3}
areaChart
yAxisTextStyle={{color: 'lightgray'}}
data={latestData}
curved
startFillColor={'rgb(84,219,234)'}
endFillColor={'rgb(84,219,234)'}
startOpacity={0.4}
endOpacity={0.4}
spacing={38}
backgroundColor="#414141"
rulesColor="gray"
rulesType="solid"
initialSpacing={10}
yAxisColor="lightgray"
xAxisColor="lightgray"
dataPointsHeight={20}
dataPointsWidth={20}
/>
<View>
<View
style={{
marginVertical: 100,
paddingVertical: 50,
backgroundColor: '#414141',
}}>
<LineChart
isAnimated
thickness={3}
color="#07BAD1"
maxValue={600}
noOfSections={3}
animateOnDataChange
animationDuration={1000}
onDataChangeAnimationDuration={300}
areaChart
yAxisTextStyle={{color: 'lightgray'}}
data={currentData}
// curved
hideDataPoints
startFillColor={'rgb(84,219,234)'}
endFillColor={'rgb(84,219,234)'}
startOpacity={0.4}
endOpacity={0.1}
spacing={22}
backgroundColor="#414141"
rulesColor="gray"
rulesType="solid"
initialSpacing={10}
yAxisColor="lightgray"
xAxisColor="lightgray"
dataPointsHeight={20}
dataPointsWidth={20}
/>
</View>
{/* <TouchableOpacity
onPress={() => setCurrentData(latestData)}
style={{padding: 12, backgroundColor: 'lightgreen', marginBottom: 15}}>
<Text>Smooth</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => setCurrentData(latestData2)}
style={{padding: 12, backgroundColor: 'lightgreen', marginBottom: 15}}>
<Text>Smooth Low</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => setCurrentData(latestData3)}
style={{padding: 12, backgroundColor: 'lightgreen', marginBottom: 15}}>
<Text>Edged</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => setCurrentData(latestData4)}
style={{padding: 12, backgroundColor: 'lightgreen', marginBottom: 15}}>
<Text>Edged Low</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => setCurrentData(latestData5)}
style={{padding: 12, backgroundColor: 'lightgreen'}}>
<Text>Straight</Text>
</TouchableOpacity> */}
{/* {!toggle ? (
<BarChart

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@ -2,22 +2,24 @@
### Basic props
| Prop | Type | Description | Default value |
| ------------------- | -------------- | --------------------------------------------------------------------------------------- | ------------------- |
| data | Array of items | An item object represents a point in the line chart. It is described in the next table. | \_ |
| data2 | Array of items | Second set of dataPoint for the second line | \_ |
| data3 | Array of items | Third set of dataPoint for the third line | \_ |
| width | number | Width of the Bar chart | width of the parent |
| height | number | Height of the Bar chart (excluding the bottom label) | 200 |
| maxValue | number | Maximum value shown in the Y axis | 200 |
| noOfSections | number | Number of sections in the Y axis | 10 |
| stepValue | number | Value of 1 step/section in the Y axis | 20 |
| stepHeight | number | Height of 1 step/section in the Y axis | 20 |
| spacing | number | Distance between 2 consecutive bars in the Bar chart | 20 |
| backgroundColor | ColorValue | Background color of the Bar chart | \_ |
| disableScroll | Boolean | To disable horizontal scroll | false |
| showScrollIndicator | Boolean | To show horizontal scroll indicator | false |
| isAnimated | Boolean | To show animates Line or Area Chart. Animation occurs onLoad and on value change | false |
| Prop | Type | Description | Default value |
| ----------------------------- | -------------- | -------------------------------------------------------------------------------------------------- | ------------------- |
| data | Array of items | An item object represents a point in the line chart. It is described in the next table. | \_ |
| data2 | Array of items | Second set of dataPoint for the second line | \_ |
| data3 | Array of items | Third set of dataPoint for the third line | \_ |
| width | number | Width of the Bar chart | width of the parent |
| height | number | Height of the Bar chart (excluding the bottom label) | 200 |
| maxValue | number | Maximum value shown in the Y axis | 200 |
| noOfSections | number | Number of sections in the Y axis | 10 |
| stepValue | number | Value of 1 step/section in the Y axis | 20 |
| stepHeight | number | Height of 1 step/section in the Y axis | 20 |
| spacing | number | Distance between 2 consecutive bars in the Bar chart | 20 |
| backgroundColor | ColorValue | Background color of the Bar chart | \_ |
| disableScroll | Boolean | To disable horizontal scroll | false |
| showScrollIndicator | Boolean | To show horizontal scroll indicator | false |
| isAnimated | Boolean | To show animated Line or Area Chart. Animation occurs when the chart load for the first time | false |
| animateOnDataChange | Boolean | To show animation on change in data. A smooth transition takes place between the iold and new line | false |
| onDataChangeAnimationDuration | number | Duration (milliseconds) in which the transition animation takes place on a change in data | 400 |
---

View File

@ -1,6 +1,6 @@
{
"name": "react-native-gifted-charts",
"version": "0.2.3",
"version": "0.2.4",
"description": "The most complete library for Bar, Line, Area, Pie and Donut charts in React Native. Allows 2D, 3D, gradient, animations and live data updates.",
"main": "src/index.tsx",
"files": [
@ -19,7 +19,7 @@
"bugs": {
"url": "https://github.com/Abhinandan-Kushwaha/react-native-gifted-charts/issues"
},
"homepage": "https://github.com/Abhinandan-Kushwaha/react-native-gifted-charts#readme",
"homepage": "https://gifted-charts.web.app/",
"publishConfig": {
"registry": "https://registry.npmjs.org/"
},

View File

@ -25,6 +25,9 @@ import Svg, {
import {svgPath, bezierCommand} from '../utils';
import Rule from '../Components/lineSvg';
let initialData = null;
let animations = [];
type propTypes = {
height?: number;
noOfSections?: number;
@ -42,7 +45,9 @@ type propTypes = {
thickness3?: number;
rotateLabel?: Boolean;
isAnimated?: Boolean;
animateOnDataChange?: Boolean;
animationDuration?: number;
onDataChangeAnimationDuration?: number;
animationEasing?: any;
animateTogether?: boolean;
xAxisThickness?: number;
@ -247,7 +252,7 @@ export const LineChart = (props: propTypes) => {
const [selectedIndex, setSelectedIndex] = useState(-1);
const containerHeight = props.height || 200;
const noOfSections = props.noOfSections || 10;
const data = useMemo(() => props.data || [], [props.data]);
let data = useMemo(() => props.data || [], [props.data]);
const data2 = useMemo(() => props.data2 || [], [props.data2]);
const data3 = useMemo(() => props.data3 || [], [props.data3]);
@ -257,7 +262,93 @@ export const LineChart = (props: propTypes) => {
const widthValue3 = useMemo(() => new Animated.Value(0), []);
const animationDuration = props.animationDuration || 800;
const onDataChangeAnimationDuration =
props.onDataChangeAnimationDuration || 400;
const animateTogether = props.animateTogether || false;
const animateOnDataChange = props.animateOnDataChange || false;
if (!initialData) {
initialData = [...data];
animations = initialData.map(item => new Animated.Value(item.value));
}
let newPoints = '',
newFillPoints = '';
let counter = 0;
if (animateOnDataChange) {
animations.forEach((item, index) => {
item.addListener(val => {
data[index].value = val.value;
let pp = '',
ppp = '';
if (!props.curved) {
for (let i = 0; i < data.length; i++) {
pp +=
'L' +
(initialSpacing - dataPointsWidth1 / 2 + spacing * i) +
' ' +
(containerHeight +
10 -
(data[i].value * containerHeight) / maxValue) +
' ';
}
if (areaChart) {
ppp =
'L' +
(initialSpacing - dataPointsWidth1 / 2) +
' ' +
(containerHeight + 10 - xAxisThickness) +
' ';
ppp += pp;
ppp +=
'L' +
(initialSpacing -
dataPointsWidth1 / 2 +
spacing * (data.length - 1)) +
' ' +
(containerHeight + 10 - xAxisThickness);
ppp +=
'L' +
(initialSpacing - dataPointsWidth1 / 2) +
' ' +
(containerHeight + 10 - xAxisThickness) +
' ';
}
newPoints = pp;
newFillPoints = ppp;
setPointsOnChange();
}
counter++;
});
});
}
const setPointsOnChange = () => {
if (counter === data.length) {
// console.log('here.......');
if (!props.curved) {
setPoints(newPoints.replace('L', 'M'));
if (areaChart) {
setFillPoints(newFillPoints.replace('L', 'M'));
}
}
}
};
useEffect(() => {
if (animateOnDataChange) {
Animated.parallel(
animations.map((anItem, index) =>
Animated.timing(anItem, {
toValue: data[index].value,
useNativeDriver: true,
duration: onDataChangeAnimationDuration,
}),
),
).start();
}
}, [animateOnDataChange, data, onDataChangeAnimationDuration]);
const labelsAppear = useCallback(() => {
opacValue.setValue(0);
@ -392,14 +483,17 @@ export const LineChart = (props: propTypes) => {
pp3 = '';
if (!props.curved) {
for (let i = 0; i < data.length; i++) {
pp +=
'L' +
(initialSpacing - dataPointsWidth1 / 2 + spacing * i) +
' ' +
(containerHeight +
10 -
(data[i].value * containerHeight) / maxValue) +
' ';
if (!animateOnDataChange) {
pp +=
'L' +
(initialSpacing - dataPointsWidth1 / 2 + spacing * i) +
' ' +
(containerHeight +
10 -
(data[i].value * containerHeight) / maxValue) +
' ';
setPoints(pp.replace('L', 'M'));
}
if (data2.length) {
pp2 +=
'L' +
@ -421,7 +515,6 @@ export const LineChart = (props: propTypes) => {
' ';
}
}
setPoints(pp.replace('L', 'M'));
setPoints2(pp2.replace('L', 'M'));
setPoints3(pp3.replace('L', 'M'));
@ -431,26 +524,29 @@ export const LineChart = (props: propTypes) => {
ppp2 = '',
ppp3 = '';
ppp =
'L' +
(initialSpacing - dataPointsWidth1 / 2) +
' ' +
(containerHeight + 10 - xAxisThickness) +
' ';
ppp += pp;
ppp +=
'L' +
(initialSpacing -
dataPointsWidth1 / 2 +
spacing * (data.length - 1)) +
' ' +
(containerHeight + 10 - xAxisThickness);
ppp +=
'L' +
(initialSpacing - dataPointsWidth1 / 2) +
' ' +
(containerHeight + 10 - xAxisThickness) +
' ';
if (!animateOnDataChange) {
ppp =
'L' +
(initialSpacing - dataPointsWidth1 / 2) +
' ' +
(containerHeight + 10 - xAxisThickness) +
' ';
ppp += pp;
ppp +=
'L' +
(initialSpacing -
dataPointsWidth1 / 2 +
spacing * (data.length - 1)) +
' ' +
(containerHeight + 10 - xAxisThickness);
ppp +=
'L' +
(initialSpacing - dataPointsWidth1 / 2) +
' ' +
(containerHeight + 10 - xAxisThickness) +
' ';
setFillPoints(ppp.replace('L', 'M'));
}
if (data2.length) {
ppp2 =
@ -499,8 +595,6 @@ export const LineChart = (props: propTypes) => {
' ';
setFillPoints3(ppp3.replace('L', 'M'));
}
setFillPoints(ppp.replace('L', 'M'));
}
// console.log('pp-------->', pp);
@ -643,6 +737,7 @@ export const LineChart = (props: propTypes) => {
/*************************************************************************************/
}
}, [
animateOnDataChange,
areaChart,
containerHeight,
data,