import React from 'react'; import {Pressable, View} from 'react-native'; import Svg, { Path, Circle, Text as SvgText, Defs, RadialGradient, Stop, G, Line, } from 'react-native-svg'; import { getPieChartMainProps, PieChartMainProps, pieColors, } from 'gifted-charts-core'; import { rnVersion } from 'react-native-gifted-charts/dist/utils'; export const PieChartMain = (props: PieChartMainProps) => { const { isThreeD, isBiggerPie, data, showInnerComponent, radius, canvasWidth, canvasHeight, shadowWidth, backgroundColor, shadowColor, semiCircle, pi, initialAngle, shadow, donut, strokeWidth, strokeColor, innerRadius, showText, textColor, textSize, tiltAngle, labelsPosition, showTextBackground, textBackgroundColor, showValuesAsLabels, showGradient, gradientCenterColor, minShiftX, minShiftY, total, horizAdjustment, vertAdjustment, cx, cy, mData, paddingHorizontal, paddingVertical, extraRadius, showExternalLabels, getExternaLabelProperties, coordinates, onPressed, font, fontWeight, fontStyle, edgesPressable, } = getPieChartMainProps(props); const{setTouchX,setTouchY} = props; let prevSide = 'right'; let prevLabelComponentX = 0; let wasFirstItemOnPole = false; const onPressHandler = (e: any) => { let x = e.nativeEvent.locationX, y = e.nativeEvent.locationY; x -= extraRadius; y -= extraRadius; setTouchX(x); setTouchY(y); const r = Math.sqrt((x - cx) ** 2 + (y - cy) ** 2); if (r > radius || (donut && r < innerRadius)) return; const a = Math.atan2(y - cy, x - cx); for (let index = 0; index < data.length; index++) { const angle = coordinates[index]; const {sx, sy, ax, ay} = angle; const startAngle = Math.atan2(sy - cy, sx - cx); const endAngle = Math.atan2(ay - cy, ax - cx); if (startAngle < endAngle) { if (startAngle < a && a < endAngle) { onPressed(data[index], index); break; } } else { if (a > startAngle || a < endAngle) { onPressed(data[index], index); break; } } } }; return ( = 720000 ? 'box-none' : 'auto'} // use 'box-none' react-native version 0.72 onwards viewBox={`${strokeWidth / -2 + minShiftX - extraRadius - paddingHorizontal / 2} ${ strokeWidth / -2 + minShiftY - extraRadius - paddingVertical / 2 } ${ (radius + extraRadius + strokeWidth) * 2 + paddingHorizontal + horizAdjustment + (horizAdjustment ? strokeWidth : 0) } ${ (radius + extraRadius + strokeWidth) * 2 + paddingVertical + vertAdjustment + (vertAdjustment ? strokeWidth : 0) }`} height={(radius + extraRadius) * 2 + strokeWidth + paddingVertical} width={(radius + extraRadius) * 2 + strokeWidth + paddingHorizontal}> {data.map((item, index) => { return ( ); })} {(data.length === 1 || !total) ? ( <> ) : ( data.map((item, index) => { const {sx, sy, ax, ay} = coordinates[index]; if (isBiggerPie && index) return null; return ( total / 2 ? 1 : 0 } 1 ${ax} ${ay} L ${cx + (item.shiftX || 0)} ${ cy + (item.shiftY || 0) }`} stroke={item.strokeColor || strokeColor} strokeWidth={ props.focusOnPress && props.selectedIndex === index ? 0 : item.strokeWidth === 0 ? 0 : item.strokeWidth || strokeWidth } fill={ props.selectedIndex === index || item.peripheral ? 'none' : showGradient ? `url(#grad${index})` : item.color || pieColors[index % 9] } /> ); }) )} {(showText || showInnerComponent || showExternalLabels) && data.map((item, index) => { const localPieInnerComponent = item.pieInnerComponent ?? props.pieInnerComponent; const pieInnerComponentHeight = props.pieInnerComponentHeight ?? 0 const pieInnerComponentWidth = props.pieInnerComponentWidth ?? 0 if (isBiggerPie && index) return null; if (!props.data[index].value) return null; 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; } } const { labelLineColor, labelLineThickness, labelComponentHeight, inX, inY, outX, outY, finalX, labelComponentX, labelComponentY, localExternalLabelComponent, isRightHalf, } = getExternaLabelProperties( item, mx, my, cx, cy, prevSide, prevLabelComponentX, index === data.length - 1, // isLast wasFirstItemOnPole, ); prevSide = isRightHalf ? 'right' : 'left'; prevLabelComponentX = labelComponentX; if (index === 0) wasFirstItemOnPole = labelComponentY !== outY; return ( {showExternalLabels ? ( {localExternalLabelComponent ? ( {localExternalLabelComponent?.(item, index) ?? null} ) : null} ) : null} {showTextBackground ? ( ) : null} {showText && ( {item.text || (showValuesAsLabels ? item.value + '' : '')} )} {localPieInnerComponent ? ( {localPieInnerComponent?.(item, index) ?? null} ) : null} ); })} {isThreeD && shadow && !semiCircle ? ( ) : null} ); };