Added Svg Pie and Donut charts!!

This commit is contained in:
Abhinandan-Kushwaha 2022-04-18 03:33:22 +05:30
parent 588703b8c9
commit f64a7a59e4
2 changed files with 473 additions and 37 deletions

204
App.js
View File

@ -5,6 +5,7 @@ import {View, Text, StyleSheet} from 'react-native';
import {MyPattern} from './src/pattern'; import {MyPattern} from './src/pattern';
import {BarChart, LineChart, PieChart} from './src'; import {BarChart, LineChart, PieChart} from './src';
import {Path, Pattern} from 'react-native-svg'; import {Path, Pattern} from 'react-native-svg';
import {SvgPie} from './src/SvgPie';
const App = () => { const App = () => {
const [toggle, setToggle] = useState(true); const [toggle, setToggle] = useState(true);
@ -551,11 +552,11 @@ const App = () => {
); );
}; };
const styleObject = { // const styleObject = {
marginLeft: -95, // marginLeft: -95,
paddingLeft: 120, // paddingLeft: 120,
transform: [{rotate: '90deg'}], // transform: [{rotate: '90deg'}],
}; // };
const ddtt = [ const ddtt = [
{ {
value: 10, value: 10,
@ -682,7 +683,7 @@ const App = () => {
{value: 0.85, label: '15'}, {value: 0.85, label: '15'},
]; ];
const lineData = [ const lineData = [
{value: 8,pointerShiftX:10,pointerShiftY:-10}, {value: 8, pointerShiftX: 10, pointerShiftY: -10},
{value: 10}, {value: 10},
{value: 12}, {value: 12},
{value: 8}, {value: 8},
@ -734,21 +735,85 @@ const App = () => {
// {value: 85, dataPointText: '85'}, // {value: 85, dataPointText: '85'},
// ]; // ];
const styleObject = {
marginLeft: -95,
paddingLeft: 110,
transform: [{rotate: '90deg'}],
// backgroundColor: 'red',
};
const lineData1 = [ const lineData1 = [
{value: 20,pointerShiftX:10}, {
{value: 40}, value: 10000,
{value: 48, onPress:(item)=>Alert.alert(item.value+'')}, barMarginBottom: 20,
{value: 50}, label: 'hello world',
{value: 56}, labelTextStyle: styleObject,
{value: 70}, labelWidth: 130,
{value: 90}, },
{value: 95}, {
{value: 70}, value: 40000,
{value: 90}, label: 'hello world',
{value: 95}, labelTextStyle: styleObject,
labelWidth: 130,
},
{
value: 48000,
onPress: item => Alert.alert(item.value + ''),
label: 'hello world',
labelTextStyle: styleObject,
labelWidth: 130,
},
{
value: 50000,
label: 'hello world',
labelTextStyle: styleObject,
labelWidth: 130,
},
{
value: 56000,
barMarginBottom: 40,
label: 'hello world',
labelTextStyle: styleObject,
labelWidth: 130,
},
{
value: 70000,
label: 'hello world',
labelTextStyle: styleObject,
labelWidth: 130,
},
{
value: 90000,
label: 'hello world',
labelTextStyle: styleObject,
labelWidth: 130,
},
{
value: 95000,
label: 'hello world',
labelTextStyle: styleObject,
labelWidth: 130,
},
{
value: 70000,
label: 'hello world',
labelTextStyle: styleObject,
labelWidth: 130,
},
{
value: 90000,
label: 'hello world',
labelTextStyle: styleObject,
labelWidth: 130,
},
{
value: 95000,
label: 'hello world',
labelTextStyle: styleObject,
labelWidth: 130,
},
]; ];
const lineData2 = [ const lineData2 = [
{value: 0},
{value: 5}, {value: 5},
{value: 8}, {value: 8},
{value: 18}, {value: 18},
@ -817,36 +882,99 @@ const App = () => {
style={{ style={{
// flex: 1, // flex: 1,
paddingVertical: 100, paddingVertical: 100,
backgroundColor: 'black', paddingLeft:20,
// backgroundColor: 'black',
}}> }}>
{/* <MyPattern/> */} {/* <MyPattern/> */}
<LineChart {/* <PieChart
data={lineData1} data={lineData2.reverse()}
areaChart // initialAngle={Math.PI}
showText
showValuesAsLabels
/> */}
<SvgPie
// backgroundColor='black'
donut
// isThreeD
// shiftInnerCenterX={20}
semiCircle
shadow
radius={150}
// shadow
// innerCircleBorderWidth={4}
showText
showValuesAsLabels
textSize={10}
fontWeight='bold'
// font='monospace'
// labelsPosition="inward"
data={[{value: 500}, {value: 20}, {value: 40}, {value: 80}, {value: 30}]}
/>
{/* <PieChart donut innerCircleBorderWidth={3} innerCircleBorderColor='lightgray' shiftInnerCenterX={15} shadow data={[{value:50},{value:20},{value:40},{value:80},{value:30}]} /> */}
{/* <BarChart
data={lineData2}
showText
showValuesAsLabels
// horizontalRulesStyle={{zIndex:100}}
// backgroundColor='black'
// color='white'
// dataPointsColor1='red'
// rotateLabel
labelsExtraHeight={100}
// areaChart
// barMarginBottom={10}
// isAnimated // isAnimated
curved // isThreeD
dataPointsShape='rectangular' // showGradient
cappedBars
capColor={'red'}
// curved
// dataPointsShape="rectangular"
// cappedBars
// yAxisSide='right' // yAxisSide='right'
// pressEnabled // pressEnabled
// showStripOnPress // showStripOnPress
// pointerConfig={{pointerStripColor: 'blue'}} // pointerConfig={{pointerStripColor: 'blue'}}
initialSpacing={0} // initialSpacing={0}
hideRules // hideRules
// scrollToEnd // scrollToEnd
// horizontalRulesStyle={{zIndex:1}} // horizontalRulesStyle={{zIndex:1}}
// backgroundColor='rgba(255,0,0,0.8)' // backgroundColor='rgba(255,0,0,0.8)'
// yAxisLabelContainerStyle={{zIndex:100000,elevation:1,textAlign:'left'}} // yAxisLabelContainerStyle={{zIndex:100000,elevation:1,textAlign:'left'}}
// yAxisTextStyle={{fontWeight:'bold',marginRight:-110,zIndex:10000,textAlign:'left'}} // yAxisTextStyle={{fontWeight:'bold',marginRight:-110,zIndex:10000,textAlign:'left'}}
// spacing={30} // spacing={30}
/> /> */}
{/* <BarChart {/* <BarChart
data={ldt} data={ldt}
maxValue={80} areaChart
stepValue={20} // maxValue={80}
noOfSections={4} // stepValue={20}
minValue={-60} // noOfSections={4}
noOfSectionsBelowXAxis={3} // minValue={-60}
frontColor={'yellow'}
yAxisThickness={5}
width={260}
yAxisSide='right'
yAxisTextStyle={{left:40}}
// yAxisLabelContainerStyle={{zIndex:20,elevation:10}}
// noOfSectionsBelowXAxis={3}
showReferenceLine1
referenceLine1Position={40}
referenceLine1Config={{
labelText: 'hello',
labelTextStyle: {left:100,top:-10},
type: 'solid'
}}
showReferenceLine2
referenceLine2Position={60}
referenceLine2Config={{
color:'red',
labelText: 'hello',
labelTextStyle: {left:100,top:-10},
type: 'solid'
}}
// width={190}
// hideRules
/> */} /> */}
{/* <LineChart {/* <LineChart
areaChart areaChart
@ -891,7 +1019,7 @@ const App = () => {
</View> */} </View> */}
{/* <PieChart data={[]} isThreeD shadow donut/> */} {/* <PieChart data={[]} isThreeD shadow donut/> */}
<LineChart {/* <LineChart
data={lineData} data={lineData}
initialSpacing={0} initialSpacing={0}
spacing={12} spacing={12}
@ -904,7 +1032,7 @@ const App = () => {
hideRules hideRules
xAxisColor="white" xAxisColor="white"
yAxisColor="white" yAxisColor="white"
yAxisTextStyle={{color:'white'}} yAxisTextStyle={{color: 'white'}}
height={250} height={250}
pointerConfig={{ pointerConfig={{
color: 'white', color: 'white',
@ -913,12 +1041,14 @@ const App = () => {
pointerLabelComponent: item => { pointerLabelComponent: item => {
return ( return (
<View> <View>
<Text style={{color:'yellow',fontWeight:'bold'}}>{item.value}</Text> <Text style={{color: 'yellow', fontWeight: 'bold'}}>
{item.value}
</Text>
</View> </View>
); );
}, },
}} }}
/> /> */}
{/* <LineChart {/* <LineChart
curved={true} curved={true}

306
src/SvgPie/index.tsx Normal file
View File

@ -0,0 +1,306 @@
import React from 'react';
import {ColorValue, View, Text} from 'react-native';
import Svg, {
Path,
LinearGradient,
Stop,
Circle,
Rect,
Text as CanvasText,
Line,
} from 'react-native-svg';
import {svgPath, bezierCommand} from '../utils';
type propTypes = {
radius?: number;
isThreeD?: Boolean;
donut?: Boolean;
innerRadius?: number;
shadow?: Boolean;
innerCircleColor?: ColorValue;
innerCircleBorderWidth?: number;
innerCircleBorderColor?: ColorValue;
shiftInnerCenterX?: number;
shiftInnerCenterY?: number;
shadowColor?: string;
shadowWidth?: number;
strokeWidth?: number;
strokeColor?: string;
backgroundColor?: string;
data: Array<itemType>;
semiCircle?: Boolean;
showText?: Boolean;
textColor?: string;
textSize?: number;
fontStyle?: string;
fontWeight?: string;
font?: string;
showTextBackground?: Boolean;
textBackgroundColor?: string;
textBackgroundRadius?: number;
showValuesAsLabels?: Boolean;
centerLabelComponent?: Function;
tilt?: number;
initialAngle?: number;
labelsPosition?: 'outward' | 'inward' | 'mid';
};
type itemType = {
value: number;
shiftX?: number;
shiftY?: number;
color?: string;
text?: string;
textColor?: string;
textSize?: number;
fontStyle?: string;
fontWeight?: string;
font?: string;
textBackgroundColor?: string;
textBackgroundRadius?: number;
shiftTextX?: number;
shiftTextY?: number;
};
export const SvgPie = (props: propTypes) => {
const {data, isThreeD} = props;
const radius = props.radius || 120;
const canvasWidth = radius * 2;
const canvasHeight = isThreeD ? radius * 2.3 : radius * 2;
const shadowWidth = props.shadowWidth || (6 * radius) / 5;
const backgroundColor = props.backgroundColor || 'transparent';
const shadowColor = props.shadowColor || 'lightgray';
const semiCircle = props.semiCircle || false;
let pi = Math.PI;
const initialAngle = props.initialAngle || (semiCircle ? pi / -2 : 0);
const shadow = props.shadow || false;
const donut = props.donut || false;
const innerRadius = props.innerRadius || radius / 2;
const innerCircleColor =
props.innerCircleColor || props.backgroundColor || 'white';
const innerCircleBorderWidth =
props.innerCircleBorderWidth || (props.innerCircleBorderColor ? 5 : 0);
const innerCircleBorderColor = props.innerCircleBorderColor || 'lightgray';
const shiftInnerCenterX = props.shiftInnerCenterX || 0;
const shiftInnerCenterY = props.shiftInnerCenterY || 0;
const strokeWidth = props.strokeWidth || 0;
const strokeColor =
props.strokeColor || (strokeWidth ? 'gray' : 'transparent');
const showText = props.showText || false;
const textColor = props.textColor || '';
const textSize = props.textSize ? Math.min(props.textSize, radius / 5) : 16;
const tilt = props.tilt ? Math.min(props.tilt, 1) : props.isThreeD ? 0.5 : 1;
const labelsPosition = props.labelsPosition
? props.labelsPosition
: donut
? 'outward'
: 'mid';
const showTextBackground = props.showTextBackground || false;
const textBackgroundColor = props.textBackgroundColor || 'white';
const showValuesAsLabels = props.showValuesAsLabels || false;
const fontStyleList = ['normal', 'italic', 'oblique'];
const fontWeightList = [
'normal',
'bold',
'bolder',
'lighter',
'100',
'200',
'300',
'400',
'500',
'600',
'700',
'800',
'900',
];
const colors = [
'cyan',
'green',
'orange',
'purple',
'yellow',
'red',
'blue',
'pink',
];
let isDataShifted = false;
data.forEach((item: any) => {
total += item.value;
if (item.shiftX || item.shiftY) {
isDataShifted = true;
}
});
if (semiCircle) {
pi = Math.PI / 2;
}
let cx = radius,
cy = radius;
let total = data.map(item => item.value).reduce((v, a) => v + a);
console.log('total ------->', total);
let acc = 0;
let pData = data.map(item => {
acc += item.value / total;
return acc;
});
acc = 0;
let mData = data.map(item => {
let pAcc = acc;
acc += item.value / total;
return pAcc + (acc - pAcc) / 2;
});
pData = [0, ...pData];
// mData = [0, ...mData];
console.log('pdata----....----....---->>>>', pData);
return (
<View
style={[
{
backgroundColor: backgroundColor,
height: canvasHeight,
width: canvasWidth,
},
isThreeD && {transform: [{rotateX: '55deg'}]},
]}>
<Svg>
{isThreeD && shadow && !semiCircle && (
<Circle
cx={cx}
cy={shadowWidth}
r={radius}
stroke={shadowColor}
strokeWidth="1.5"
fill={shadowColor}
/>
)}
{data.map((item, index) => {
console.log('index', index);
let nextItem;
if (index === pData.length - 1) nextItem = pData[0];
else nextItem = pData[index + 1];
let sx = cx * (1 + Math.sin(2 * pi * pData[index] + initialAngle));
let sy = cy * (1 - Math.cos(2 * pi * pData[index] + initialAngle));
let ax = cx * (1 + Math.sin(2 * pi * nextItem + initialAngle));
let ay = cy * (1 - Math.cos(2 * pi * nextItem + initialAngle));
// console.log('sx', sx);
// console.log('sy', sy);
// console.log('ax', ax);
// console.log('ay', ay);
return (
<Path
d={`M ${cx} ${cy} L ${sx} ${sy} A ${radius} ${radius} 0 ${
semiCircle ? 0 : data[index].value > total / 2 ? 1 : 0
} 1 ${ax} ${ay} L ${cx} ${cy}`}
stroke={strokeColor}
strokeWidth={strokeWidth}
fill={item.color || colors[index % 9]}
/>
);
})}
{showText &&
data.map((item, index) => {
console.log('index', index);
let mx = cx * (1 + Math.sin(2 * pi * mData[index] + initialAngle));
let my = cy * (1 - Math.cos(2 * pi * mData[index] + initialAngle));
let midx = (mx + cx) / 2;
let midy = (my + cy) / 2;
let x = midx,
y = midy;
if (labelsPosition === 'outward') {
x = (midx + mx) / 2;
y = (midy + my) / 2;
} else if (labelsPosition === 'inward') {
x = (midx + cx) / 2;
y = (midy + cy) / 2;
}
// console.log('sx', sx);
// console.log('sy', sy);
// console.log('ax', ax);
// console.log('ay', ay);
return (
<>
{/* <Line x1={mx} x2={cx} y1={my} y2={cy} stroke="black" /> */}
<Circle
cx={x}
cy={y - (item.textSize || textSize) / 4}
r={
item.textBackgroundRadius ||
props.textBackgroundRadius ||
item.textSize ||
textSize
}
fill={item.textBackgroundColor || textBackgroundColor}
/>
<CanvasText
fill={item.textColor || textColor || colors[(index + 2) % 9]}
fontSize={item.textSize || textSize}
fontFamily={item.font || props.font}
fontWeight={item.fontWeight || props.fontWeight}
x={x + (item.shiftTextX || 0) - (item.textSize || textSize)/1.8}
y={y + (item.shiftTextY || 0)}>
{item.text || (showValuesAsLabels ? item.value + '' : '')}
</CanvasText>
</>
);
})}
</Svg>
{(props.centerLabelComponent || (donut && !isDataShifted)) && (
<View
style={[
{
height: innerRadius * 2,
width: innerRadius * 2,
borderRadius: innerRadius,
position: 'absolute',
zIndex: 100,
alignSelf: 'center',
backgroundColor: innerCircleColor,
left: canvasWidth / 2 - innerRadius + shiftInnerCenterX,
top:
canvasHeight / 2 -
innerRadius +
shiftInnerCenterY -
(isThreeD ? radius / 5 : 0),
borderWidth: innerCircleBorderWidth,
borderColor: innerCircleBorderColor,
justifyContent: 'center',
alignItems: 'center',
},
isThreeD && {
borderTopWidth: innerCircleBorderWidth * 5,
borderLeftWidth: shiftInnerCenterX
? innerCircleBorderWidth * 2
: innerCircleBorderWidth,
},
semiCircle && {
borderTopWidth: isThreeD
? innerCircleBorderWidth * 5
: innerCircleBorderWidth,
borderLeftWidth: 0.5,
borderLeftColor: innerCircleColor,
borderBottomWidth: 0,
borderRightWidth: 0.5,
borderRightColor: innerCircleColor,
},
]}>
{props.centerLabelComponent ? props.centerLabelComponent() : null}
</View>
)}
</View>
);
};