Added individual datapoints to line chart

This commit is contained in:
Abhinandan Kushwaha 2021-08-06 01:39:16 +05:30
parent c5852371ee
commit a1d7f94faf
3 changed files with 176 additions and 69 deletions

22
App.js
View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import {View, Text} from 'react-native'; import { View, Text } from 'react-native';
import {BarChart, LineChart, PieChart} from './src'; import { BarChart, LineChart, PieChart } from './src';
const App = () => { const App = () => {
// const lineData = [ // const lineData = [
@ -19,14 +19,14 @@ const App = () => {
// ]; // ];
const data = [ const data = [
{value: 15, label: 'Jan'}, { value: 15, label: 'Jan' },
{value: 40, label: 'Feb'}, { value: 40, label: 'Feb', showDataPoint: true, dataPointShape: 'rectangular', dataPointHeight: 12, dataPointWidth: 12, },
{value: 10, label: 'Mar'}, { value: 10, label: 'Mar', showDataPoint: true, dataPointShape: 'rectangular', dataPointHeight: 20, dataPointWidth: 20, },
{value: 30, label: 'Apr'}, { value: 30, label: 'Apr', showDataPoint: true },
]; ];
return ( return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}> <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<View <View
style={{ style={{
// flex: 1, // flex: 1,
@ -36,7 +36,13 @@ const App = () => {
alignItems: 'center', alignItems: 'center',
}}> }}>
<View> <View>
<LineChart data={data} /> <LineChart
data={data}
hideDataPoints
// dataPointsShape='rectangular'
// dataPointsHeight={12}
// dataPointsWidth={12}
/>
{/* <BarChart {/* <BarChart
showGradient showGradient
isThreeD isThreeD

View File

@ -46,6 +46,12 @@ So, all the three must be used together. Using any 1 or 2 of them may produce ab
| textShiftY | number | To shift the dataPointText text vertically | | textShiftY | number | To shift the dataPointText text vertically |
| textColor | ColorValue | Color of the dataPointText | | textColor | ColorValue | Color of the dataPointText |
| textFontSize | number | Font size of the dataPointText | | textFontSize | number | Font size of the dataPointText |
| showDataPoint | Boolean | To show data point for the particular item |
| dataPointHeight | number | Height of the data point (when data point's shape is rectangular)|
| dataPointWidth | number | Width of the data point (when data point's shape is rectangular) |
| dataPointRadius | number | Radius of the data point (when data points' shape is circular)
| dataPointColor | ColorValue | Color of the data point |
| dataPointShape | string | Shape of the data point (rectangular or circular) defaults to circular |
---- ----

View File

@ -1,4 +1,4 @@
import React, {Fragment, useEffect, useState} from 'react'; import React, { Fragment, useEffect, useState } from 'react';
import { import {
View, View,
ScrollView, ScrollView,
@ -7,7 +7,7 @@ import {
Text, Text,
ColorValue, ColorValue,
} from 'react-native'; } from 'react-native';
import {styles} from './styles'; import { styles } from './styles';
import Svg, { import Svg, {
Path, Path,
LinearGradient, LinearGradient,
@ -16,7 +16,7 @@ import Svg, {
Rect, Rect,
Text as CanvasText, Text as CanvasText,
} from 'react-native-svg'; } from 'react-native-svg';
import {svgPath, bezierCommand} from '../utils'; import { svgPath, bezierCommand } from '../utils';
type propTypes = { type propTypes = {
height?: number; height?: number;
@ -127,6 +127,13 @@ type itemType = {
textShiftY?: number; textShiftY?: number;
textColor?: string; textColor?: string;
textFontSize?: number; textFontSize?: number;
showDataPoint?: Boolean;
dataPointHeight?: number;
dataPointWidth?: number;
dataPointRadius?: number;
dataPointColor?: string;
dataPointShape?: string;
}; };
type sectionType = { type sectionType = {
@ -155,7 +162,7 @@ export const LineChart = (props: propTypes) => {
const maxValue = props.maxValue || maxItem; const maxValue = props.maxValue || maxItem;
const horizSections = [{value: 0}]; const horizSections = [{ value: 0 }];
const stepHeight = props.stepHeight || containerHeight / noOfSections; const stepHeight = props.stepHeight || containerHeight / noOfSections;
const stepValue = props.stepValue || maxValue / noOfSections; const stepValue = props.stepValue || maxValue / noOfSections;
const initialSpacing = const initialSpacing =
@ -260,7 +267,7 @@ export const LineChart = (props: propTypes) => {
// console.log('data', data); // console.log('data', data);
horizSections.pop(); horizSections.pop();
for (let i = 0; i <= noOfSections; i++) { for (let i = 0; i <= noOfSections; i++) {
horizSections.push({value: maxValue - stepValue * i}); horizSections.push({ value: maxValue - stepValue * i });
} }
useEffect(() => { useEffect(() => {
@ -472,9 +479,9 @@ export const LineChart = (props: propTypes) => {
justifyContent: 'center', justifyContent: 'center',
// alignSelf: 'center' // alignSelf: 'center'
}, },
rotateLabel && {transform: [{rotate: '60deg'}]}, rotateLabel && { transform: [{ rotate: '60deg' }] },
]}> ]}>
<Text style={[labelTextStyle, {textAlign: 'center'}]} numberOfLines={1}> <Text style={[labelTextStyle, { textAlign: 'center' }]} numberOfLines={1}>
{label || ''} {label || ''}
</Text> </Text>
</View> </View>
@ -502,9 +509,9 @@ export const LineChart = (props: propTypes) => {
left: initialSpacing + spacing * index - spacing / 2, left: initialSpacing + spacing * index - spacing / 2,
opacity: appearingOpacity, opacity: appearingOpacity,
}, },
rotateLabel && {transform: [{rotate: '60deg'}]}, rotateLabel && { transform: [{ rotate: '60deg' }] },
]}> ]}>
<Text style={[labelTextStyle, {textAlign: 'center'}]} numberOfLines={1}> <Text style={[labelTextStyle, { textAlign: 'center' }]} numberOfLines={1}>
{label || ''} {label || ''}
</Text> </Text>
</Animated.View> </Animated.View>
@ -614,7 +621,7 @@ export const LineChart = (props: propTypes) => {
<View <View
style={[ style={[
styles.line, styles.line,
{height: xAxisThickness, backgroundColor: xAxisColor}, { height: xAxisThickness, backgroundColor: xAxisColor },
]} ]}
/> />
) : hideRules ? null : ( ) : hideRules ? null : (
@ -646,6 +653,86 @@ export const LineChart = (props: propTypes) => {
); );
}; };
const renderSpecificDataPoints = (dataForRender) => {
return dataForRender.map((item: itemType, index: number) => {
if (item.showDataPoint) {
if (item.dataPointShape === 'rectangular') {
return (
<Fragment key={index}>
<Rect
x={initialSpacing - (item.dataPointWidth || 2) / 2 - 1 + spacing * index}
y={
containerHeight -
(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 || 0)
}
y={
containerHeight -
(item.dataPointHeight || 2) / 2 +
10 -
(item.value * containerHeight) / maxValue +
(item.textShiftY || 0)
}>
{item.dataPointText}
</CanvasText>
)}
</Fragment>
);
}
else {
return (
<Fragment key={index}>
<Circle
cx={initialSpacing - (item.dataPointWidth || 2) / 2 + spacing * index}
cy={
containerHeight + 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 || 0)
}
y={
containerHeight -
(item.dataPointHeight || 2) / 2 +
10 -
(item.value * containerHeight) / maxValue +
(item.textShiftY || 0)
}>
{item.dataPointText}
</CanvasText>
)}
</Fragment>
)
}
}
return null;
})
}
const renderDataPoints = ( const renderDataPoints = (
dataForRender, dataForRender,
dataPointsShape, dataPointsShape,
@ -785,7 +872,7 @@ export const LineChart = (props: propTypes) => {
strokeWidth={currentLineThickness || thickness} strokeWidth={currentLineThickness || thickness}
/> />
)} )}
{!hideDataPoints1 && {!hideDataPoints1 ?
renderDataPoints( renderDataPoints(
data, data,
dataPointsShape1, dataPointsShape1,
@ -795,8 +882,11 @@ export const LineChart = (props: propTypes) => {
dataPointsRadius1, dataPointsRadius1,
textColor1, textColor1,
textFontSize1, textFontSize1,
)} )
{!hideDataPoints2 && :
renderSpecificDataPoints(data)
}
{!hideDataPoints2 ?
renderDataPoints( renderDataPoints(
data2, data2,
dataPointsShape2, dataPointsShape2,
@ -806,7 +896,10 @@ export const LineChart = (props: propTypes) => {
dataPointsRadius2, dataPointsRadius2,
textColor2, textColor2,
textFontSize2, textFontSize2,
)} )
:
renderSpecificDataPoints(data2)
}
</Svg> </Svg>
</View> </View>
); );
@ -868,7 +961,7 @@ export const LineChart = (props: propTypes) => {
strokeWidth={currentLineThickness || thickness} strokeWidth={currentLineThickness || thickness}
/> />
)} )}
{!hideDataPoints1 && {!hideDataPoints1 ?
renderDataPoints( renderDataPoints(
data, data,
dataPointsShape1, dataPointsShape1,
@ -878,8 +971,9 @@ export const LineChart = (props: propTypes) => {
dataPointsRadius1, dataPointsRadius1,
textColor1, textColor1,
textFontSize1, textFontSize1,
)} ) :
{!hideDataPoints2 && renderSpecificDataPoints(data)}
{!hideDataPoints2 ?
renderDataPoints( renderDataPoints(
data2, data2,
dataPointsShape2, dataPointsShape2,
@ -889,14 +983,15 @@ export const LineChart = (props: propTypes) => {
dataPointsRadius2, dataPointsRadius2,
textColor2, textColor2,
textFontSize2, textFontSize2,
)} ) :
renderSpecificDataPoints(data2)}
</Svg> </Svg>
</Animated.View> </Animated.View>
); );
}; };
return ( return (
<View style={[styles.container, {height: containerHeight}]}> <View style={[styles.container, { height: containerHeight }]}>
{props.hideAxesAndRules !== true && renderHorizSections()} {props.hideAxesAndRules !== true && renderHorizSections()}
{/* {sectionsOverlay()} */} {/* {sectionsOverlay()} */}
<ScrollView <ScrollView