Added semi-circle Pie and Donut charts

This commit is contained in:
Abhinandan Kushwaha 2022-01-28 04:17:45 +05:30
parent 165ba66160
commit 1f01917b6b
4 changed files with 204 additions and 89 deletions

164
App.js
View File

@ -2,7 +2,7 @@ import React, {useEffect, useState} from 'react';
import {TouchableOpacity} from 'react-native'; import {TouchableOpacity} from 'react-native';
import {Alert} from 'react-native'; import {Alert} from 'react-native';
import {View, Text, StyleSheet} from 'react-native'; import {View, Text, StyleSheet} from 'react-native';
import {BarChart, LineChart} from './src'; import {BarChart, LineChart, PieChart} from './src';
const App = () => { const App = () => {
const [toggle, setToggle] = useState(true); const [toggle, setToggle] = useState(true);
@ -486,9 +486,9 @@ const App = () => {
); );
}; };
const ndd = [ const ndd = [
{label: 'Jan', value: 30}, {value: 30, color: 'rgb(84,219,234)'},
{label: 'Feb', value: 10}, {value: 40, color: 'lightgreen'},
{label: 'Mar', value: 20}, {value: 20, color: 'orange'},
]; ];
const [data, setData] = useState([ const [data, setData] = useState([
{value: 15, label: 'Jan'}, {value: 15, label: 'Jan'},
@ -532,44 +532,115 @@ const App = () => {
{value: 30, label: 'Dec'}, {value: 30, label: 'Dec'},
]); ]);
const renderLegend = (text, color) => {
return (
<View style={{flexDirection: 'row', marginBottom: 12}}>
<View
style={{
height: 18,
width: 18,
marginRight: 10,
borderRadius: 4,
backgroundColor: color || 'white',
}}
/>
<Text style={{color: 'white', fontSize: 16}}>{text || ''}</Text>
</View>
);
};
const barData = [
{
value: 15,
label: 'Mon',
},
{value: 30, label: 'Tue'},
{value: 26, label: 'Wed'},
// {value: 40, label: 'Thu'},
{value: 16, label: 'Wed'},
{value: 40, label: 'Thu'},
];
return ( return (
<View> <View
<View style={{
marginVertical: 100,
marginLeft: 6,
}}>
{/* <BarChart backgroundColor={'green'} data={barData} /> */}
<PieChart
backgroundColor={'red'}
maxValue={40}
data={barData}
height={140}
radius={170}
donut={true}
showText={true}
showValuesAsLabels={true}
semiCircle={true}
isThreeD={true}
// shiftInnerCenterY={100}
shadow={true}
strokeWidth={5}
innerCircleBorderColor={'gray'}
// showTextBackground={true}
/>
{/* <View
style={{ style={{
marginVertical: 100, marginVertical: 100,
marginHorizontal: 30,
borderRadius: 10,
paddingVertical: 50, paddingVertical: 50,
// backgroundColor: '#414141', backgroundColor: '#414141',
justifyContent: 'center',
alignItems: 'center',
}}> }}>
<BarChart hideOrigin data={ndd} yAxisLabelTexts={['0', '£10', '£20']} /> <Text
{/* <LineChart style={{
isAnimated color: 'white',
thickness={3} fontSize: 32,
color="#07BAD1" fontWeight: 'bold',
maxValue={600} marginBottom: 12,
noOfSections={3} }}>
animateOnDataChange Quarterly Sales
animationDuration={1000} </Text>
onDataChangeAnimationDuration={300} <PieChart
areaChart strokeColor="white"
yAxisTextStyle={{color: 'lightgray'}} strokeWidth={4}
data={currentData} donut
// curved data={[
hideDataPoints {value: 30, color: 'rgb(84,219,234)'},
startFillColor={'rgb(84,219,234)'} {value: 40, color: 'lightgreen'},
endFillColor={'rgb(84,219,234)'} {value: 20, color: 'orange'},
startOpacity={0.4} ]}
endOpacity={0.1} innerCircleColor="#414141"
spacing={22} innerCircleBorderWidth={4}
backgroundColor="#414141" innerCircleBorderColor={'white'}
rulesColor="gray" showValuesAsLabels={true}
rulesType="solid" showText
initialSpacing={10} textSize={18}
yAxisColor="lightgray" showTextBackground={true}
xAxisColor="lightgray" centerLabelComponent={() => {
dataPointsHeight={20} return (
dataPointsWidth={20} <View>
/> */} <Text style={{color: 'white', fontSize: 36}}>90</Text>
</View> <Text style={{color: 'white', fontSize: 18}}>Total</Text>
</View>
);
}}
/>
<View
style={{
width: '100%',
flexDirection: 'row',
justifyContent: 'space-evenly',
marginTop: 20,
}}>
{renderLegend('Jan', 'rgb(84,219,234)')}
{renderLegend('Feb', 'lightgreen')}
{renderLegend('Mar', 'orange')}
</View>
</View> */}
{/* <TouchableOpacity {/* <TouchableOpacity
onPress={() => setCurrentData(latestData)} onPress={() => setCurrentData(latestData)}
@ -597,13 +668,15 @@ const App = () => {
<Text>Straight</Text> <Text>Straight</Text>
</TouchableOpacity> */} </TouchableOpacity> */}
{/* {!toggle ? ( {/* {true ? (
<BarChart <LineChart
isThreeD isThreeD
key={'xyz'} key={'xyz'}
height={300} height={320}
maxValue={360} maxValue={360}
showLine showLine
hideOrigin
// animationDuration={000}
initialSpacing={30} initialSpacing={30}
// showVerticalLines // showVerticalLines
lineConfig={{ lineConfig={{
@ -619,12 +692,17 @@ const App = () => {
shiftY: 25, shiftY: 25,
curved: true, curved: true,
}} }}
yAxisLabelPrefix={'$'}
yAxisLabelSuffix={'.0'}
barWidth={32} barWidth={32}
// width={190} // width={190}
data={[ data={[
{ {
value: 270, value: 70,
label: 'Jan', label: 'Jan',
topLabelComponent: () => {
return <Text>30</Text>;
},
}, },
{value: 250, label: 'Feb'}, {value: 250, label: 'Feb'},
{value: 200, label: 'Mar'}, {value: 200, label: 'Mar'},
@ -672,8 +750,8 @@ const App = () => {
capColor={'rgb(78, 0, 142)'} capColor={'rgb(78, 0, 142)'}
capThickness={4} capThickness={4}
// barWidth={35} // barWidth={35}
frontColor={'rgba(200, 100, 244,0.2)'} gradientColor={'rgba(200, 100, 244,0.2)'}
gradientColor={'rgba(78, 0, 142,1)'} frontColor={'rgba(78, 0, 142,1)'}
// rulesType="dashed" // rulesType="dashed"
// rulesColor={'rgba(0,200,0,0.5)'} // rulesColor={'rgba(0,200,0,0.5)'}
// rulesThickness={1} // rulesThickness={1}

View File

@ -1,27 +1,28 @@
# Pie Chart props # Pie Chart props
| Prop | Type | Description | Default value | | Prop | Type | Description | Default value |
| -------------------- | -------------- | -------------------------------------------------------------------------------- | --------------- | | -------------------- | -------------- | --------------------------------------------------------------------------------------------------------- | --------------- |
| data | Array of items | An item object represents a section in the Pie chart. Descibed in the next table | \_ | | data | Array of items | An item object represents a section in the Pie chart. Descibed in the next table | \_ |
| radius | number | Radius of the Pie chart | 120 | | radius | number | Radius of the Pie chart | 120 |
| isThreeD | Boolean | If set to true, it rotates and translates the chart to give it a 3D effect | false | | isThreeD | Boolean | If set to true, it rotates and translates the chart to give it a 3D effect | false |
| shadow | Boolean | Shadow to the Pie chart, when set to true, it enhances the 3D effect | false | | shadow | Boolean | Shadow to the Pie chart, when set to true, it enhances the 3D effect | false |
| shadowColor | ColorValue | Color of the shadow | lightgray | | shadowColor | ColorValue | Color of the shadow | lightgray |
| shadowWidth | number | Width of the shadow | radius\*4/3 | | shadowWidth | number | Width of the shadow | radius\*4/3 |
| strokeWidth | number | Stroke (line) width for the Pie chart and its section | 0 | | strokeWidth | number | Stroke (line) width for the Pie chart and its section | 0 |
| strokeColor | ColorValue | Stroke (line) color | gray | | strokeColor | ColorValue | Stroke (line) color | gray |
| backgroundColor | ColorValue | Background color of the container that contains the Pie chart | white | | backgroundColor | ColorValue | Background color of the container that contains the Pie chart | white |
| showText | Boolean | When set to true, displays text on the Pie sections | false | | showText | Boolean | When set to true, displays text on the Pie sections | false |
| textColor | ColorValue | Color of the label texts | random colors | | textColor | ColorValue | Color of the label texts | random colors |
| textSize | number | Size of the label texts (max allowed: radius / 5) | 16 | | textSize | number | Size of the label texts (max allowed: radius / 5) | 16 |
| fontStyle | string | Style of the text - 'normal', 'italic' or 'oblique' | 'normal' | | fontStyle | string | Style of the text - 'normal', 'italic' or 'oblique' | 'normal' |
| fontWeight | string | Weight of the text - 'bold', 'bolder', 'lighter', '100', '200' etc | 'normal' | | fontWeight | string | Weight of the text - 'bold', 'bolder', 'lighter', '100', '200' etc | 'normal' |
| font | string | Font family of the text - 'Arial', 'Cursive', 'Comic Sans MS' etc | 'Comic Sans MS' | | font | string | Font family of the text - 'Arial', 'Cursive', 'Comic Sans MS' etc | 'Comic Sans MS' |
| showTextBackground | Boolean | When set to true, displays background for text on the Pie sections | false | | showTextBackground | Boolean | When set to true, displays background for text on the Pie sections | false |
| textBackgroundColor | ColorValue | Background color for the label texts | white | | textBackgroundColor | ColorValue | Background color for the label texts | white |
| textBackgroundRadius | number | Radius for the background of the text labels | textSize | | textBackgroundRadius | number | Radius for the background of the text labels | textSize |
| showValuesAsLabels | Boolean | When set to true, the values of the Pie sections are displayed as labels | false | | showValuesAsLabels | Boolean | When set to true, the values of the Pie sections are displayed as labels | false |
| centerLabelComponent | Function | Component to be rendered at the center of the Pie chart | \_ | | centerLabelComponent | Function | Component to be rendered at the center of the Pie chart | \_ |
| semiCircle | Boolean | When set to true, renders the Pie Chart in a semi-circle. donut semiCircle charts look like a speed-meter | false |
### Item description ### Item description

View File

@ -1,6 +1,6 @@
{ {
"name": "react-native-gifted-charts", "name": "react-native-gifted-charts",
"version": "0.2.9", "version": "1.0.0",
"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.", "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", "main": "src/index.tsx",
"files": [ "files": [

View File

@ -2,8 +2,6 @@ import React from 'react';
import {ColorValue, View} from 'react-native'; import {ColorValue, View} from 'react-native';
import Canvas from 'react-native-canvas'; import Canvas from 'react-native-canvas';
const pi = Math.PI;
type propTypes = { type propTypes = {
radius?: number; radius?: number;
isThreeD?: Boolean; isThreeD?: Boolean;
@ -21,6 +19,7 @@ type propTypes = {
strokeColor?: string; strokeColor?: string;
backgroundColor?: string; backgroundColor?: string;
data: Array<itemType>; data: Array<itemType>;
semiCircle?: Boolean;
showText?: Boolean; showText?: Boolean;
textColor?: string; textColor?: string;
@ -59,6 +58,7 @@ export const PieChart = (props: propTypes) => {
const backgroundColor = props.backgroundColor || 'white'; const backgroundColor = props.backgroundColor || 'white';
const shadowColor = props.shadowColor || 'lightgray'; const shadowColor = props.shadowColor || 'lightgray';
let total = 0; let total = 0;
let pi = Math.PI;
const shadow = props.shadow || false; const shadow = props.shadow || false;
const donut = props.donut || false; const donut = props.donut || false;
const innerRadius = props.innerRadius || radius / 2; const innerRadius = props.innerRadius || radius / 2;
@ -79,7 +79,7 @@ export const PieChart = (props: propTypes) => {
const showTextBackground = props.showTextBackground || false; const showTextBackground = props.showTextBackground || false;
const showValuesAsLabels = props.showValuesAsLabels || false; const showValuesAsLabels = props.showValuesAsLabels || false;
const semiCircle = props.semiCircle || false;
const fontStyleList = ['normal', 'italic', 'oblique']; const fontStyleList = ['normal', 'italic', 'oblique'];
const fontWeightList = [ const fontWeightList = [
'normal', 'normal',
@ -105,6 +105,10 @@ export const PieChart = (props: propTypes) => {
} }
}); });
if (semiCircle) {
pi = Math.PI / 2;
}
const canvasHeight = isThreeD ? radius * 2.5 + 60 : radius * 2 + 60; const canvasHeight = isThreeD ? radius * 2.5 + 60 : radius * 2 + 60;
const canvasWidth = radius * 2 + 60; const canvasWidth = radius * 2 + 60;
@ -125,7 +129,7 @@ export const PieChart = (props: propTypes) => {
const initialValue = 30; const initialValue = 30;
/****************** SHADOW ***************/ /****************** SHADOW ***************/
if (isThreeD && shadow) { if (!semiCircle && isThreeD && shadow) {
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(initialValue, radius + initialValue); ctx.moveTo(initialValue, radius + initialValue);
ctx.lineTo(initialValue, shadowWidth + initialValue); ctx.lineTo(initialValue, shadowWidth + initialValue);
@ -230,7 +234,7 @@ export const PieChart = (props: propTypes) => {
radius + initialValue + shiftY, radius + initialValue + shiftY,
); );
ctx.fillStyle = dataItem.color || colors[i++ % 8]; ctx.fillStyle = dataItem.color || colors[i++ % 9];
ctx.fill(); ctx.fill();
// Stroke at the end again // Stroke at the end again
@ -297,29 +301,41 @@ export const PieChart = (props: propTypes) => {
// console.log('semisum==>>', semiSum); // console.log('semisum==>>', semiSum);
// console.log('sin(semisum)==>>', Math.sin(semiSum)); // console.log('sin(semisum)==>>', Math.sin(semiSum));
if (semiSum > 0 && semiSum <= pi / 2) { if (semiCircle) {
xx -= 40; if (semiSum > 0 && semiSum <= pi / 2) {
yy -= 10; yy -= 6;
} else if (semiSum > pi / 2 && semiSum <= pi) { } else if (semiSum > pi / 2 && semiSum <= pi) {
xx += 10; yy -= 10;
yy -= 10; } else if (semiSum > pi && semiSum <= 1.5 * pi) {
} else if (semiSum > pi && semiSum <= 1.5 * pi) { xx += 10;
xx += 10; yy -= 20;
yy += 24; } else {
xx += 25;
yy -= 8;
}
} else { } else {
xx -= 40; if (semiSum > 0 && semiSum <= pi / 2) {
yy += 24; xx -= 20;
} else if (semiSum > pi && semiSum <= 1.5 * pi) {
xx += 10;
yy += 16;
} else if (semiSum > 1.5 * pi) {
xx -= 16;
yy += 16;
}
} }
if (showTextBackground && (dataItem.text || showValuesAsLabels)) { if (showTextBackground && (dataItem.text || showValuesAsLabels)) {
let textBackgroundX = let textBackgroundX =
xx + xx -
(semiCircle ? 18 : 0) +
(props.textBackgroundRadius || (props.textBackgroundRadius ||
dataItem.textBackgroundRadius || dataItem.textBackgroundRadius ||
textSize) / textSize) /
2; 2;
let textBackgroundY = let textBackgroundY =
yy - yy +
(semiCircle ? 8 : 0) -
(props.textBackgroundRadius || (props.textBackgroundRadius ||
dataItem.textBackgroundRadius || dataItem.textBackgroundRadius ||
textSize) / textSize) /
@ -332,7 +348,7 @@ export const PieChart = (props: propTypes) => {
dataItem.textBackgroundRadius || dataItem.textBackgroundRadius ||
textSize, textSize,
0, 0,
2 * pi, 2 * Math.PI,
false, false,
); );
ctx.fillStyle = ctx.fillStyle =
@ -345,12 +361,20 @@ export const PieChart = (props: propTypes) => {
xx += shiftTextX; xx += shiftTextX;
yy += shiftTextY; yy += shiftTextY;
ctx.fillStyle = dataItem.textColor || textColor || colors[i++ % 8]; ctx.fillStyle = dataItem.textColor || textColor || colors[i++ % 9];
let labelText = dataItem.text || ''; let labelText = dataItem.text || '';
if (showValuesAsLabels && !labelText) { if (showValuesAsLabels && !labelText) {
labelText = dataItem.value.toString(); labelText = dataItem.value.toString();
} }
ctx.fillText(labelText, xx, yy); if (semiCircle) {
ctx.translate(xx, yy);
ctx.rotate(Math.PI);
ctx.fillText(labelText, 4, 4);
ctx.rotate(Math.PI);
ctx.translate(-xx, -yy);
} else {
ctx.fillText(labelText, xx, yy);
}
} }
/****************************************************************************************/ /****************************************************************************************/
@ -361,7 +385,10 @@ export const PieChart = (props: propTypes) => {
return total === 0 ? null : ( return total === 0 ? null : (
<View style={{transform: [{scaleY: tilt}]}}> <View style={{transform: [{scaleY: tilt}]}}>
<Canvas ref={handleCanvas} /> <Canvas
style={semiCircle && {transform: [{rotate: '180deg'}]}}
ref={handleCanvas}
/>
{(props.centerLabelComponent || (donut && !isDataShifted)) && ( {(props.centerLabelComponent || (donut && !isDataShifted)) && (
<View <View
style={[ style={[
@ -375,7 +402,8 @@ export const PieChart = (props: propTypes) => {
top: top:
canvasHeight / 2 - canvasHeight / 2 -
innerRadius * (isThreeD ? 1.5 : 1) + innerRadius * (isThreeD ? 1.5 : 1) +
shiftInnerCenterY, shiftInnerCenterY +
(isThreeD && semiCircle ? radius / 2 : 0),
borderWidth: innerCircleBorderWidth, borderWidth: innerCircleBorderWidth,
borderColor: innerCircleBorderColor, borderColor: innerCircleBorderColor,
backgroundColor: innerCircleColor, backgroundColor: innerCircleColor,
@ -388,6 +416,14 @@ export const PieChart = (props: propTypes) => {
? innerCircleBorderWidth * 2 ? innerCircleBorderWidth * 2
: innerCircleBorderWidth, : innerCircleBorderWidth,
}, },
semiCircle && {
borderTopWidth: isThreeD
? innerCircleBorderWidth * 5
: innerCircleBorderWidth,
borderLeftWidth: 0.001,
borderBottomWidth: 0,
borderRightWidth: 0.001,
},
]}> ]}>
{props.centerLabelComponent ? props.centerLabelComponent() : null} {props.centerLabelComponent ? props.centerLabelComponent() : null}
</View> </View>