ARTICLE AD BOX
I have Chart component that has been used in multiple places and based on the area allocated it can be any size small or large. I have no issues with large size pie, and I have added a logic to hide datalabel if slice size is less than 10%.
However, if slice is big, but pie size is small in that case inside datalabels overflows either out of the pie or overflows into the other slice.
I want to hide any datalabels that is not fitting completely inside its own slice.
Here, if 88.8B is not fitting in the slice, hence it should get hide.
I have added this code to hide the datalabels. It works in some cases, but not working for all the cases.
const canFitInsideSlice = (pointLabel: Highcharts.PointLabelObject, labelText: string): boolean => { const point = pointLabel.point as Highcharts.Point & { shapeArgs?: any }; const shapeArgs = point?.shapeArgs; if (!shapeArgs || !pointLabel.series?.chart?.renderer) { return false; } const start = Number(shapeArgs.start ?? 0); const end = Number(shapeArgs.end ?? 0); const outerRadius = Number(shapeArgs.r ?? 0); const innerRadius = Number(shapeArgs.innerR ?? 0); const sliceAngle = Math.max(end - start, 0); const radialThickness = Math.max(outerRadius - innerRadius, 0); const arcLength = sliceAngle * ((outerRadius + innerRadius) / 2); const tempText = pointLabel.series.chart.renderer.text(labelText, 0, 0) .css({ fontSize: `${fontSize}`, fontWeight: 'normal' }) .add(); const textBounds = tempText.getBBox(); tempText.destroy(); return arcLength >= textBounds.width + 8 && radialThickness >= textBounds.height + 6; };Datalabel code:
dataLabels: [{ // Outside Data Label for slices enabled: chartComponent.chartJSON?.chart?.showLabels == 1 || chartComponent.chartJSON?.chart?.showValues == 1, inside: (chartComponent.chartJSON?.chart?.placevaluesInside == 1), style: { fontWeight: 'normal', textOutline: 'none', fontSize: fontSize, width: '300px', textOverflow: 'ellipsis' }, alignTo: 'connector', connectorShape: 'fixedOffset', defer: true, backgroundColor: 'auto', borderRadius: 8, padding: 8, formatter(this: Highcharts.PointLabelObject) { // eslint-disable-next-line @typescript-eslint/no-this-alias const point = this; const textColor = chartComponent.getContrastColor(point.color) const showValue = chartComponent.isSliceSmall(point.percentage) && chartJson?.chart?.showValues == 1; const showPercentValues = chartJson.chart?.showPercentValues == 1; const abbreviatedValue = showPercentValues ? `${point.percentage.toFixed(2)}%` : chartComponent.abbreviateNumber(point.y); const label = chartJson?.chart?.showLabels == 1 || showValue ? `<span style="color:${textColor}"> <span>${chartJson?.chart?.showLabels == 1 ? point.key : ''}</span> <span>${showValue ? abbreviatedValue : ''}</span> </span>` : undefined; return label; }, distance: 30, connectorPadding: 0, }, { // Inside text for slices enabled: chartComponent.chartJSON?.chart?.showValues == 1, inside: (chartComponent.chartJSON?.chart?.placevaluesInside == 1), style: { fontWeight: 'normal', textOutline: 'none', fontSize: this.getChartComponentProperty('_fontSize') }, defer: true, allowOverlap: false, crop: false, overflow: 'none', formatter(this: Highcharts.PointLabelObject) { // eslint-disable-next-line @typescript-eslint/no-this-alias const point = this; const textColor = chartComponent.getContrastColor(point.color) const smallSlice = chartComponent.isSliceSmall(point.percentage); const showPercentValues = chartJson.chart?.showPercentValues == 1; const abbreviatedValue = showPercentValues ? `${point.percentage.toFixed(2)}%` : chartComponent.abbreviateNumber(point.y); if (!canFitInsideSlice(point, abbreviatedValue)) { return null; } if (!smallSlice) { return `<span style="color:${textColor};display:inline-block;text-align:center;">${abbreviatedValue}</span>`; } return; }, distance: '-40%' }] as Highcharts.SeriesPieDataLabelsOptionsObject,