From c9156ab4eaec36a882fc033f77885dcd607a41ee Mon Sep 17 00:00:00 2001 From: Abhinandan Kushwaha Date: Mon, 16 Sep 2024 03:09:31 +0530 Subject: [PATCH 1/3] v1.4.39 Fixed onPress in Pie & handled empty data in Line --- docs/PieChart/PieChartProps.md | 4 +- package.json | 4 +- release-notes/release-notes.md | 18 + src/PieChart/index.tsx | 2 +- src/PieChart/main.tsx | 670 +++++++++++++++++---------------- 5 files changed, 364 insertions(+), 334 deletions(-) diff --git a/docs/PieChart/PieChartProps.md b/docs/PieChart/PieChartProps.md index 0cd9f732..0cdee159 100644 --- a/docs/PieChart/PieChartProps.md +++ b/docs/PieChart/PieChartProps.md @@ -15,7 +15,7 @@ | inwardExtraLengthForFocused | number | Extra length of focused Pie section towards the center (only for donut charts) | 0 | | sectionAutoFocus | boolean | In case you don't want focusOnPress but want a particular section to autofocus, this prop will be needed | false | | focusedPieIndex | number | index of the initially focused Pie, works only when focusOnPress is true | -1 | -| onLabelPress | Function | Callback function called on press of a Label (takes item and index as parameter) | onPress OR null | +| onLabelPress (removed) | 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 | | shadowColor | ColorValue | Color of the shadow | lightgray | @@ -117,7 +117,7 @@ type LabelLineConfig = { | textBackgroundRadius | number | Radius for the background of the text label | | labelPosition | string | Tells where inside the Pie sections should the labels be shown- 'onBorder', 'outward', 'inward' or 'mid' | | onPress | Function | Callback function called on press of Pie sections (takes item and index as parameter) | -| onLabelPress | Function | Callback function called on press of a Label (takes item and index as parameter) | +| onLabelPress (removed) | Function | Callback function called on press of a Label (takes item and index as parameter) | | strokeWidth | number | Stroke (line) width for the Pie chart and its section | | strokeColor | ColorValue | Stroke (line) color | | focused | boolean | When set to true, the section for that item is focused, sectionAutoFocus must be set true in order to use this property | diff --git a/package.json b/package.json index 10c04f37..dcec647a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-gifted-charts", - "version": "1.4.38", + "version": "1.4.39", "description": "The most complete library for Bar, Line, Area, Pie, Donut, Stacked Bar and Population Pyramid charts in React Native. Allows 2D, 3D, gradient, animations and live data updates.", "main": "dist/index.js", "files": [ @@ -25,7 +25,7 @@ "registry": "https://registry.npmjs.org/" }, "dependencies": { - "gifted-charts-core": "0.1.38" + "gifted-charts-core": "0.1.40" }, "devDependencies": { "@babel/cli": "^7.24.8", diff --git a/release-notes/release-notes.md b/release-notes/release-notes.md index 402ad99c..60c87ea4 100644 --- a/release-notes/release-notes.md +++ b/release-notes/release-notes.md @@ -1,3 +1,21 @@ +# 🎉 1.4.37 + +## 🐛 Bug fixes + +1. Fixed the issue- "onPress pressing/focusing wrong Pie section". It fixes these issues- + 1. https://github.com/Abhinandan-Kushwaha/react-native-gifted-charts/issues/832 + 2. https://github.com/Abhinandan-Kushwaha/react-native-gifted-charts/issues/297 + 3. https://github.com/Abhinandan-Kushwaha/react-native-gifted-charts/issues/812
+ As a part of this fix, removed `onLabelPress` which is still there in types, but will not be functional. Will try to restore it in future. + +2. Fixed the issue- "Line charts crash if data is an empty array." See https://github.com/Abhinandan-Kushwaha/react-native-gifted-charts/issues/707 + +--- + +--- + +--- + # 🎉 1.4.38 Fixed the issue- "Line chart inside Bar chart misaligned if data contains -ve values" diff --git a/src/PieChart/index.tsx b/src/PieChart/index.tsx index 765c9b8e..602a551e 100644 --- a/src/PieChart/index.tsx +++ b/src/PieChart/index.tsx @@ -143,7 +143,7 @@ export const PieChart = (props: PieChartPropsType) => { }, { value: total - props.data[selectedIndex].value, - onPress: () => alert('black'), + // onPress: () => alert('black'), peripheral: true, strokeWidth: 0, }, diff --git a/src/PieChart/main.tsx b/src/PieChart/main.tsx index 57da6767..219963d6 100644 --- a/src/PieChart/main.tsx +++ b/src/PieChart/main.tsx @@ -1,5 +1,9 @@ import React from 'react'; -import {View} from 'react-native'; +import { + GestureResponderEvent, + TouchableWithoutFeedback, + View, +} from 'react-native'; import Svg, { Path, Circle, @@ -62,358 +66,366 @@ export const PieChartMain = (props: PieChartMainProps) => { extraRadius, showExternalLabels, getExternaLabelProperties, + coordinates, + onPressed, } = getPieChartMainProps(props); let prevSide = 'right'; let prevLabelComponentX = 0; let wasFirstItemOnPole = false; - 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 ? ( - <> - { - 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); + const onPressHandler = (e: GestureResponderEvent) => { + const rad = radius; + let {locationX: x, locationY: y} = e.nativeEvent; + x -= extraRadius; + y -= extraRadius; + const r = Math.sqrt((x - cx) ** 2 + (y - cy) ** 2); + if (r > rad) return; + const a = Math.atan2(y - cy, x - cx); - if (isBiggerPie && index) return null; + for (let index = 0; index < data.length; index++) { + const angle = coordinates[index]; + const {sx, sy, ax, ay} = angle; - 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 - } + 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 ? ( + <> + { - if (item.onPress) { - item.onPress(); - } else if (props.onPress) { - props.onPress(item, index); + // onPress={() => { + // data[0].onPress + // ? data[0].onPress() + // : props.onPress + // ? props.onPress(data[0], 0) + // : null; + // }} + /> + + ) : ( + 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 } - if (props.focusOnPress) { - if (props.selectedIndex === index || props.isBiggerPie) { - if (toggleFocusOnPress) { - props.setSelectedIndex(-1); - } - } else { - props.setSelectedIndex(index); - } + 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; - 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)); + {(showText || showInnerComponent || showExternalLabels) && + data.map((item, index) => { + const localPieInnerComponent = + item.pieInnerComponent ?? props.pieInnerComponent; + 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 midx = (mx + cx) / 2; + let midy = (my + cy) / 2; - let x = midx, - y = midy; + let x = midx, + y = midy; - const labelPosition = item.labelPosition || labelsPosition; + 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; - } + 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; + 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; + 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; + 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 ? ( - - - + {showExternalLabels ? ( + + + + {localExternalLabelComponent ? ( + + {localExternalLabelComponent?.(item, index) ?? null} + + ) : null} + + ) : null} + {showTextBackground ? ( + { + // 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); + // } + // } + // }} /> - {localExternalLabelComponent ? ( - - {localExternalLabelComponent?.(item, index) ?? null} - - ) : null} - - ) : null} - {showTextBackground ? ( - { - 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); - } + ) : null} + {showText && ( + - ) : null} - {showText && ( - { - 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); - } + 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 } - }}> - {item.text || (showValuesAsLabels ? item.value + '' : '')} - - )} - {localPieInnerComponent ? ( - - {localPieInnerComponent?.(item, index) ?? null} - - ) : null} - - ); - })} - - {isThreeD && shadow && !semiCircle ? ( - - ) : null} - + 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 + '' : '')} + + )} + {localPieInnerComponent ? ( + + {localPieInnerComponent?.(item, index) ?? null} + + ) : null} + + ); + })} + + {isThreeD && shadow && !semiCircle ? ( + + ) : null} + + ); }; From 1164725a149d0a4ae39ce18af5818d6b92be521f Mon Sep 17 00:00:00 2001 From: Abhinandan Kushwaha Date: Mon, 16 Sep 2024 03:11:10 +0530 Subject: [PATCH 2/3] fixed typo in Release-notes --- release-notes/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release-notes/release-notes.md b/release-notes/release-notes.md index 60c87ea4..11a104d8 100644 --- a/release-notes/release-notes.md +++ b/release-notes/release-notes.md @@ -1,4 +1,4 @@ -# 🎉 1.4.37 +# 🎉 1.4.39 ## 🐛 Bug fixes From c4c6dab11eb09d00bce243e77becfe0efdf8d6ae Mon Sep 17 00:00:00 2001 From: Abhinandan Kushwaha Date: Mon, 16 Sep 2024 03:13:06 +0530 Subject: [PATCH 3/3] removed unnecessary variable rad --- src/PieChart/main.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/PieChart/main.tsx b/src/PieChart/main.tsx index 219963d6..c3316cb9 100644 --- a/src/PieChart/main.tsx +++ b/src/PieChart/main.tsx @@ -75,12 +75,11 @@ export const PieChartMain = (props: PieChartMainProps) => { let wasFirstItemOnPole = false; const onPressHandler = (e: GestureResponderEvent) => { - const rad = radius; let {locationX: x, locationY: y} = e.nativeEvent; x -= extraRadius; y -= extraRadius; const r = Math.sqrt((x - cx) ** 2 + (y - cy) ** 2); - if (r > rad) return; + if (r > radius) return; const a = Math.atan2(y - cy, x - cx); for (let index = 0; index < data.length; index++) {