Added focusOnPress to Pie and Donut charts

This commit is contained in:
Abhinandan-Kushwaha 2022-05-27 05:03:45 +05:30
parent 8727ee2898
commit 94ddd27b10
4 changed files with 573 additions and 399 deletions

View File

@ -9,6 +9,9 @@
| showGradient | Boolean | Prop to enable radial gradient for the Pie sections | false |
| gradientCenterColor | ColorValue | Gradient color at the center of the Pie chart | 'white' |
| onPress | Function | Callback function called on press of Pie sections (takes item and index as parameter) | null |
| focusOnPress | Boolean | When set to true, the pressed section of the Pie chart will have a bigger radius, hence appear focused | false |
| toggleFocusOnPress | Boolean | When set to true, if the user presses an already focused pie section, it will be unfocused | true |
| extraRadiusForFocused | number | Extra radius for the focused Pie section | radius/10 |
| onLabelPress | Function | Callback function called on press of a Label (takes item and index as parameter) | onPress OR null |
| tiltAngle | Angle in deg | The angle by which the chart should be tilted | '55deg' for 3D charts, otherwise 0 |
| shadow | Boolean | Shadow to the Pie chart, when set to true, it enhances the 3D effect | false |

10
src/PieChart/colors.js Normal file
View File

@ -0,0 +1,10 @@
export const colors = [
'cyan',
'green',
'orange',
'purple',
'#bbff00',
'red',
'blue',
'pink',
];

View File

@ -1,14 +1,8 @@
import React from 'react';
import {ColorValue, View} from 'react-native';
import Svg, {
Path,
Circle,
Text as SvgText,
FontStyle,
Defs,
RadialGradient,
Stop,
} from 'react-native-svg';
import React, {useState} from 'react';
import {View, ColorValue} from 'react-native';
import {colors} from './colors';
import {PieChartMain} from './main';
import {FontStyle} from 'react-native-svg';
type propTypes = {
radius?: number;
@ -47,7 +41,12 @@ type propTypes = {
showGradient?: boolean;
gradientCenterColor?: string;
onPress?: Function;
focusOnPress?: Boolean;
toggleFocusOnPress?: Boolean;
selectedIndex?: number;
setSelectedIndex?: Function;
onLabelPress?: Function;
extraRadiusForFocused?: number;
};
type itemType = {
value: number;
@ -71,399 +70,69 @@ type itemType = {
};
export const PieChart = (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 || 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 strokeWidth = props.strokeWidth || 0;
const strokeColor =
props.strokeColor || (strokeWidth ? 'gray' : 'transparent');
const innerRadius = props.innerRadius || radius / 2.5;
const innerCircleColor =
props.innerCircleColor || props.backgroundColor || 'white';
const innerCircleBorderWidth =
props.innerCircleBorderWidth ||
(props.innerCircleBorderColor ? strokeWidth || 2 : 0);
const innerCircleBorderColor = props.innerCircleBorderColor || 'lightgray';
const shiftInnerCenterX = props.shiftInnerCenterX || 0;
const shiftInnerCenterY = props.shiftInnerCenterY || 0;
const extraRadiusForFocused = props.extraRadiusForFocused || radius / 10;
const pi = props.semiCircle ? Math.PI / 2 : Math.PI;
const [selectedIndex, setSelectedIndex] = useState(-1);
const showText = props.showText || false;
const textColor = props.textColor || '';
const textSize = props.textSize ? Math.min(props.textSize, radius / 5) : 16;
let tiltAngle = props.tiltAngle || '55deg';
if (
tiltAngle &&
!isNaN(Number(tiltAngle)) &&
!(tiltAngle + '').endsWith('deg')
) {
tiltAngle += 'deg';
}
// const tilt = props.tilt ? Math.min(props.tilt, 1) : props.isThreeD ? 0.5 : 1;
const labelsPosition = props.labelsPosition
? props.labelsPosition
: donut || props.centerLabelComponent
? 'outward'
: 'mid';
const showTextBackground = props.showTextBackground || false;
const textBackgroundColor = props.textBackgroundColor || 'white';
const showValuesAsLabels = props.showValuesAsLabels || false;
const showGradient = props.showGradient || false;
const gradientCenterColor = props.gradientCenterColor || 'white';
const colors = [
'cyan',
'green',
'orange',
'purple',
'yellow',
'red',
'blue',
'pink',
];
let isDataShifted = false;
let minShiftX = 0,
maxShiftX = 0,
minShiftY = 0,
maxShiftY = 0;
data.forEach((item: any) => {
total += item.value;
if (item.shiftX || item.shiftY) {
isDataShifted = true;
if (minShiftX > item.shiftX) {
minShiftX = item.shiftX;
}
if (minShiftY > item.shiftY) {
minShiftY = item.shiftY;
}
if (maxShiftX < item.shiftX) {
maxShiftX = item.shiftX;
}
if (maxShiftY < item.shiftY) {
maxShiftY = item.shiftY;
if (props.data.length <= 1 || !props.focusOnPress || selectedIndex === -1) {
return (
<PieChartMain
{...props}
key="pie"
setSelectedIndex={setSelectedIndex}
selectedIndex={selectedIndex}
/>
);
} else {
let startAngle = props.initialAngle || (props.semiCircle ? -pi : 0);
// let startColor;
let total = 0;
props.data.forEach(item => {
total += item.value;
});
if (selectedIndex !== 0) {
let start = 0;
for (let i = 0; i < selectedIndex; i++) {
start += props.data[i].value;
}
startAngle += (2 * pi * start) / total;
}
});
const horizAdjustment = maxShiftX - minShiftX;
const vertAdjustment = maxShiftY - minShiftY;
if (semiCircle) {
pi = Math.PI / 2;
}
let cx = radius,
cy = radius;
let total =
data && data.length
? data.map(item => item.value).reduce((v, a) => v + a)
: 0;
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];
return (
<View
style={[
{
backgroundColor: backgroundColor,
height: semiCircle ? canvasHeight / 2 : canvasHeight,
width: canvasWidth,
overflow: 'hidden',
},
isThreeD && {transform: [{rotateX: tiltAngle}]},
]}>
<Svg
viewBox={`${strokeWidth / -2 + minShiftX} ${
strokeWidth / -2 + minShiftY
} ${
(radius + strokeWidth) * 2 +
horizAdjustment +
(horizAdjustment ? strokeWidth : 0)
} ${
(radius + strokeWidth) * 2 +
+vertAdjustment +
(vertAdjustment ? strokeWidth : 0)
}`}
height={radius * 2 + strokeWidth}
width={radius * 2 + strokeWidth}>
<Defs>
{data.map((item, index) => {
return (
<RadialGradient
key={index + ''}
id={'grad' + index}
cx="50%"
cy="50%"
rx="50%"
ry="50%"
fx="50%"
fy="50%"
gradientUnits="userSpaceOnUse">
<Stop
offset="0%"
stopColor={item.gradientCenterColor || gradientCenterColor}
stopOpacity="1"
/>
<Stop
offset="100%"
stopColor={item.color || colors[index % 9]}
stopOpacity="1"
/>
</RadialGradient>
);
})}
</Defs>
{data.length === 1 ? (
<>
<Circle
cx={cx}
cy={cy}
r={radius}
fill={
showGradient ? `url(#grad${0})` : data[0].color || colors[0 % 9]
}
onPress={() => {
data[0].onPress
? data[0].onPress
: props.onPress
? props.onPress(data[0], 0)
: null;
}}
/>
</>
) : (
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)) +
(item.shiftX || 0);
let sy =
cy * (1 - Math.cos(2 * pi * pData[index] + initialAngle)) +
(item.shiftY || 0);
let ax =
cx * (1 + Math.sin(2 * pi * nextItem + initialAngle)) +
(item.shiftX || 0);
let ay =
cy * (1 - Math.cos(2 * pi * nextItem + initialAngle)) +
(item.shiftY || 0);
// console.log('sx', sx);
// console.log('sy', sy);
// console.log('ax', ax);
// console.log('ay', ay);
return (
<Path
key={index + 'a'}
d={`M ${cx + (item.shiftX || 0)} ${
cy + (item.shiftY || 0)
} L ${sx} ${sy} A ${radius} ${radius} 0 ${
semiCircle ? 0 : data[index].value > total / 2 ? 1 : 0
} 1 ${ax} ${ay} L ${cx + (item.shiftX || 0)} ${
cy + (item.shiftY || 0)
}`}
stroke={strokeColor}
strokeWidth={strokeWidth}
fill={
showGradient
? `url(#grad${index})`
: item.color || colors[index % 9]
}
onPress={() => {
item.onPress
? item.onPress
: props.onPress
? props.onPress(item, index)
: null;
}}
/>
);
})
)}
{showText &&
data.map((item, 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;
const labelPosition = item.labelPosition || labelsPosition;
if (labelPosition === 'onBorder') {
x = mx;
y = my;
} else if (labelPosition === 'outward') {
x = (midx + mx) / 2;
y = (midy + my) / 2;
} else if (labelPosition === 'inward') {
x = (midx + cx) / 2;
y = (midy + cy) / 2;
}
x += item.shiftX || 0;
y += item.shiftY || 0;
if (data.length === 1) {
if (donut) {
y =
(radius -
innerRadius +
(item.textBackgroundRadius ||
props.textBackgroundRadius ||
item.textSize ||
textSize)) /
2;
} else {
y = cy;
}
}
// 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" /> */}
{showTextBackground && (
<Circle
key={index + 'b'}
cx={x}
cy={y - (item.textSize || textSize) / 4}
r={
item.textBackgroundRadius ||
props.textBackgroundRadius ||
item.textSize ||
textSize
}
fill={item.textBackgroundColor || textBackgroundColor}
onPress={() => {
item.onLabelPress
? item.onLabelPress()
: props.onLabelPress
? props.onLabelPress(item, index)
: item.onPress
? item.onPress()
: props.onPress
? props.onPress(item, index)
: null;
}}
/>
)}
<SvgText
fill={item.textColor || textColor || colors[(index + 2) % 9]}
fontSize={item.textSize || textSize}
fontFamily={item.font || props.font}
fontWeight={item.fontWeight || props.fontWeight}
fontStyle={item.fontStyle || props.fontStyle || 'normal'}
x={
x +
(item.shiftTextX || 0) -
(item.textSize || textSize) / 1.8
}
y={y + (item.shiftTextY || 0)}
onPress={() => {
item.onLabelPress
? item.onLabelPress()
: props.onLabelPress
? props.onLabelPress(item, index)
: item.onPress
? item.onPress()
: props.onPress
? props.onPress(item, index)
: null;
}}>
{item.text || (showValuesAsLabels ? item.value + '' : '')}
</SvgText>
</>
);
})}
</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 &&
isThreeD && {
borderTopWidth: isThreeD
? innerCircleBorderWidth * 5
: innerCircleBorderWidth,
borderLeftWidth: 0.5,
borderLeftColor: innerCircleColor,
borderBottomWidth: 0,
borderRightWidth: 0.5,
borderRightColor: innerCircleColor,
},
]}>
<View style={{marginTop: semiCircle ? -0.5 * innerRadius : 0}}>
{props.centerLabelComponent ? props.centerLabelComponent() : null}
</View>
</View>
)}
{isThreeD && shadow && !semiCircle ? (
return (
<View>
<View
style={{
width: radius * 2,
height: radius * 2,
backgroundColor: shadowColor,
borderRadius: radius,
position: 'absolute',
top: shadowWidth,
zIndex: -1,
}}
/>
) : null}
</View>
);
top: -extraRadiusForFocused,
left: -extraRadiusForFocused,
}}>
<PieChartMain
{...props}
data={[
{
value: props.data[selectedIndex].value,
color:
props.data[selectedIndex].color || colors[selectedIndex % 9],
},
{
value: total - props.data[selectedIndex].value,
color: 'transparent',
},
]}
key="pie"
radius={radius + extraRadiusForFocused}
initialAngle={startAngle}
/>
</View>
<View style={{position: 'absolute'}}>
<PieChartMain
{...props}
key="pie"
selectedIndex={selectedIndex}
setSelectedIndex={setSelectedIndex}
/>
</View>
</View>
);
}
};

492
src/PieChart/main.tsx Normal file
View File

@ -0,0 +1,492 @@
import React from 'react';
import {ColorValue, View} from 'react-native';
import Svg, {
Path,
Circle,
Text as SvgText,
FontStyle,
Defs,
RadialGradient,
Stop,
} from 'react-native-svg';
import {colors} from './colors';
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?: FontStyle;
fontWeight?: string;
font?: string;
showTextBackground?: Boolean;
textBackgroundColor?: string;
textBackgroundRadius?: number;
showValuesAsLabels?: Boolean;
centerLabelComponent?: Function;
tiltAngle?: string;
initialAngle?: number;
labelsPosition?: 'onBorder' | 'outward' | 'inward' | 'mid';
showGradient?: boolean;
gradientCenterColor?: string;
onPress?: Function;
focusOnPress?: Boolean;
toggleFocusOnPress?: Boolean;
selectedIndex?: number;
setSelectedIndex?: Function;
onLabelPress?: Function;
};
type itemType = {
value: number;
shiftX?: number;
shiftY?: number;
color?: string;
gradientCenterColor?: string;
text?: string;
textColor?: string;
textSize?: number;
fontStyle?: FontStyle;
fontWeight?: string;
font?: string;
textBackgroundColor?: string;
textBackgroundRadius?: number;
shiftTextX?: number;
shiftTextY?: number;
labelPosition?: 'onBorder' | 'outward' | 'inward' | 'mid';
onPress?: Function;
onLabelPress?: Function;
};
export const PieChartMain = (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 || 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 strokeWidth = props.strokeWidth || 0;
const strokeColor =
props.strokeColor || (strokeWidth ? 'gray' : 'transparent');
const innerRadius = props.innerRadius || radius / 2.5;
const innerCircleColor =
props.innerCircleColor || props.backgroundColor || 'white';
const innerCircleBorderWidth =
props.innerCircleBorderWidth ||
(props.innerCircleBorderColor ? strokeWidth || 2 : 0);
const innerCircleBorderColor = props.innerCircleBorderColor || 'lightgray';
const shiftInnerCenterX = props.shiftInnerCenterX || 0;
const shiftInnerCenterY = props.shiftInnerCenterY || 0;
const showText = props.showText || false;
const textColor = props.textColor || '';
const textSize = props.textSize ? Math.min(props.textSize, radius / 5) : 16;
let tiltAngle = props.tiltAngle || '55deg';
if (
tiltAngle &&
!isNaN(Number(tiltAngle)) &&
!(tiltAngle + '').endsWith('deg')
) {
tiltAngle += 'deg';
}
// const tilt = props.tilt ? Math.min(props.tilt, 1) : props.isThreeD ? 0.5 : 1;
const labelsPosition = props.labelsPosition
? props.labelsPosition
: donut || props.centerLabelComponent
? 'outward'
: 'mid';
const showTextBackground = props.showTextBackground || false;
const textBackgroundColor = props.textBackgroundColor || 'white';
const showValuesAsLabels = props.showValuesAsLabels || false;
const showGradient = props.showGradient || false;
const gradientCenterColor = props.gradientCenterColor || 'white';
const toggleFocusOnPress = props.toggleFocusOnPress === false ? false : true;
let isDataShifted = false;
let minShiftX = 0,
maxShiftX = 0,
minShiftY = 0,
maxShiftY = 0;
data.forEach((item: any) => {
total += item.value;
if (item.shiftX || item.shiftY) {
isDataShifted = true;
if (minShiftX > item.shiftX) {
minShiftX = item.shiftX;
}
if (minShiftY > item.shiftY) {
minShiftY = item.shiftY;
}
if (maxShiftX < item.shiftX) {
maxShiftX = item.shiftX;
}
if (maxShiftY < item.shiftY) {
maxShiftY = item.shiftY;
}
}
});
const horizAdjustment = maxShiftX - minShiftX;
const vertAdjustment = maxShiftY - minShiftY;
if (semiCircle) {
pi = Math.PI / 2;
}
let cx = radius,
cy = radius;
let total =
data && data.length
? data.map(item => item.value).reduce((v, a) => v + a)
: 0;
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];
return (
<View
style={[
{
backgroundColor: backgroundColor,
height: semiCircle ? canvasHeight / 2 : canvasHeight,
width: canvasWidth,
overflow: 'hidden',
},
isThreeD && {transform: [{rotateX: tiltAngle}]},
]}>
<Svg
viewBox={`${strokeWidth / -2 + minShiftX} ${
strokeWidth / -2 + minShiftY
} ${
(radius + strokeWidth) * 2 +
horizAdjustment +
(horizAdjustment ? strokeWidth : 0)
} ${
(radius + strokeWidth) * 2 +
+vertAdjustment +
(vertAdjustment ? strokeWidth : 0)
}`}
height={radius * 2 + strokeWidth}
width={radius * 2 + strokeWidth}>
<Defs>
{data.map((item, index) => {
return (
<RadialGradient
key={index + ''}
id={'grad' + index}
cx="50%"
cy="50%"
rx="50%"
ry="50%"
fx="50%"
fy="50%"
gradientUnits="userSpaceOnUse">
<Stop
offset="0%"
stopColor={item.gradientCenterColor || gradientCenterColor}
stopOpacity="1"
/>
<Stop
offset="100%"
stopColor={item.color || colors[index % 9]}
stopOpacity="1"
/>
</RadialGradient>
);
})}
</Defs>
{data.length === 1 ? (
<>
<Circle
cx={cx}
cy={cy}
r={radius}
fill={
showGradient ? `url(#grad${0})` : data[0].color || colors[0 % 9]
}
onPress={() => {
data[0].onPress
? data[0].onPress()
: props.onPress
? props.onPress(data[0], 0)
: null;
}}
/>
</>
) : (
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)) +
(item.shiftX || 0);
let sy =
cy * (1 - Math.cos(2 * pi * pData[index] + initialAngle)) +
(item.shiftY || 0);
let ax =
cx * (1 + Math.sin(2 * pi * nextItem + initialAngle)) +
(item.shiftX || 0);
let ay =
cy * (1 - Math.cos(2 * pi * nextItem + initialAngle)) +
(item.shiftY || 0);
// console.log('sx', sx);
// console.log('sy', sy);
// console.log('ax', ax);
// console.log('ay', ay);
return (
<Path
key={index + 'a'}
d={`M ${cx + (item.shiftX || 0)} ${
cy + (item.shiftY || 0)
} L ${sx} ${sy} A ${radius} ${radius} 0 ${
semiCircle ? 0 : data[index].value > total / 2 ? 1 : 0
} 1 ${ax} ${ay} L ${cx + (item.shiftX || 0)} ${
cy + (item.shiftY || 0)
}`}
stroke={strokeColor}
strokeWidth={strokeWidth}
fill={
showGradient
? `url(#grad${index})`
: item.color || colors[index % 9]
}
onPress={() => {
if (item.onPress) {
item.onPress();
} else if (props.onPress) {
props.onPress(item, index);
}
if (props.focusOnPress) {
if (props.selectedIndex === index) {
if (toggleFocusOnPress) {
props.setSelectedIndex(-1);
}
} else {
props.setSelectedIndex(index);
}
}
}}
/>
);
})
)}
{showText &&
data.map((item, 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;
const labelPosition = item.labelPosition || labelsPosition;
if (labelPosition === 'onBorder') {
x = mx;
y = my;
} else if (labelPosition === 'outward') {
x = (midx + mx) / 2;
y = (midy + my) / 2;
} else if (labelPosition === 'inward') {
x = (midx + cx) / 2;
y = (midy + cy) / 2;
}
x += item.shiftX || 0;
y += item.shiftY || 0;
if (data.length === 1) {
if (donut) {
y =
(radius -
innerRadius +
(item.textBackgroundRadius ||
props.textBackgroundRadius ||
item.textSize ||
textSize)) /
2;
} else {
y = cy;
}
}
// 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" /> */}
{showTextBackground && (
<Circle
key={index + 'b'}
cx={x}
cy={y - (item.textSize || textSize) / 4}
r={
item.textBackgroundRadius ||
props.textBackgroundRadius ||
item.textSize ||
textSize
}
fill={item.textBackgroundColor || textBackgroundColor}
onPress={() => {
item.onLabelPress
? item.onLabelPress()
: props.onLabelPress
? props.onLabelPress(item, index)
: item.onPress
? item.onPress()
: props.onPress
? props.onPress(item, index)
: null;
if (props.focusOnPress) {
if (props.selectedIndex === index) {
if (toggleFocusOnPress) {
props.setSelectedIndex(-1);
}
} else {
props.setSelectedIndex(index);
}
}
}}
/>
)}
<SvgText
fill={item.textColor || textColor || colors[(index + 2) % 9]}
fontSize={item.textSize || textSize}
fontFamily={item.font || props.font}
fontWeight={item.fontWeight || props.fontWeight}
fontStyle={item.fontStyle || props.fontStyle || 'normal'}
x={
x +
(item.shiftTextX || 0) -
(item.textSize || textSize) / 1.8
}
y={y + (item.shiftTextY || 0)}
onPress={() => {
item.onLabelPress
? item.onLabelPress()
: props.onLabelPress
? props.onLabelPress(item, index)
: item.onPress
? item.onPress()
: props.onPress
? props.onPress(item, index)
: null;
if (props.focusOnPress) {
if (props.selectedIndex === index) {
if (toggleFocusOnPress) {
props.setSelectedIndex(-1);
}
} else {
props.setSelectedIndex(index);
}
}
}}>
{item.text || (showValuesAsLabels ? item.value + '' : '')}
</SvgText>
</>
);
})}
</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 &&
isThreeD && {
borderTopWidth: isThreeD
? innerCircleBorderWidth * 5
: innerCircleBorderWidth,
borderLeftWidth: 0.5,
borderLeftColor: innerCircleColor,
borderBottomWidth: 0,
borderRightWidth: 0.5,
borderRightColor: innerCircleColor,
},
]}>
<View style={{marginTop: semiCircle ? -0.5 * innerRadius : 0}}>
{props.centerLabelComponent ? props.centerLabelComponent() : null}
</View>
</View>
)}
{isThreeD && shadow && !semiCircle ? (
<View
style={{
width: radius * 2,
height: radius * 2,
backgroundColor: shadowColor,
borderRadius: radius,
position: 'absolute',
top: shadowWidth,
zIndex: -1,
}}
/>
) : null}
</View>
);
};