From 47e836b2678cb9581fe22a1690315f7e9671ccb5 Mon Sep 17 00:00:00 2001 From: przemyslawpetka Date: Fri, 13 Jun 2025 11:29:15 +0200 Subject: [PATCH] percentages on pie chart --- .../multiplatform/charts/pie/PieChart.kt | 42 +++++++++++++++++++ .../charts/pie/PieChartConfig.kt | 1 + 2 files changed, 43 insertions(+) diff --git a/charts/src/commonMain/kotlin/com/netguru/multiplatform/charts/pie/PieChart.kt b/charts/src/commonMain/kotlin/com/netguru/multiplatform/charts/pie/PieChart.kt index 9aa1974..210ac47 100644 --- a/charts/src/commonMain/kotlin/com/netguru/multiplatform/charts/pie/PieChart.kt +++ b/charts/src/commonMain/kotlin/com/netguru/multiplatform/charts/pie/PieChart.kt @@ -18,6 +18,10 @@ import androidx.compose.ui.graphics.PathOperation import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.graphics.drawscope.clipPath +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.TextLayoutResult +import androidx.compose.ui.text.drawText +import androidx.compose.ui.text.rememberTextMeasurer import com.netguru.multiplatform.charts.ChartAnimation import com.netguru.multiplatform.charts.StartAnimation import com.netguru.multiplatform.charts.mapValueToDifferentRange @@ -26,6 +30,7 @@ import com.netguru.multiplatform.charts.pie.PieDefaults.START_ANGLE import kotlin.math.PI import kotlin.math.cos import kotlin.math.min +import kotlin.math.roundToInt import kotlin.math.sin data class PieChartData(val name: String, val value: Double, val color: Color) @@ -79,6 +84,15 @@ fun PieChart( ) ) } + val textMeasurer = rememberTextMeasurer() + val textLayouts = sweepAngles.mapIndexed { index, _ -> + val percent = (data[index].value / sumOfData * 100).roundToInt() + val text = "$percent%" + val layoutResult = textMeasurer.measure( + text = AnnotatedString(text), + ) + layoutResult + } Box( modifier = modifier @@ -97,6 +111,13 @@ fun PieChart( sweepAngle = sweepAngle.toFloat(), config = config, ) + if (config.showPercentages) { + drawPercentageLabel( + textLayoutResult = textLayouts[index], + startAngle = startAngle, + sweepAngle = sweepAngle + ) + } startAngle += sweepAngle } } @@ -136,6 +157,27 @@ private fun DrawScope.drawArc( ) } +private fun DrawScope.drawPercentageLabel( + textLayoutResult: TextLayoutResult, + startAngle: Double, + sweepAngle: Double, +) { + val midAngle = startAngle + sweepAngle / 2 + val angleRad = Math.toRadians(midAngle) + val radius = size.minDimension / 2f * 0.65f + + val x = center.x + cos(angleRad).toFloat() * radius + val y = center.y + sin(angleRad).toFloat() * radius + + drawText( + textLayoutResult = textLayoutResult, + topLeft = Offset( + x - textLayoutResult.size.width / 2f, + y - textLayoutResult.size.height / 2f + ) + ) +} + private const val RIGHT_ANGLE = 90f private const val HALF_CIRCLE_ANGLE = 180f private const val FULL_CIRCLE_ANGLE = 360f diff --git a/charts/src/commonMain/kotlin/com/netguru/multiplatform/charts/pie/PieChartConfig.kt b/charts/src/commonMain/kotlin/com/netguru/multiplatform/charts/pie/PieChartConfig.kt index 55ff2ea..2781eac 100644 --- a/charts/src/commonMain/kotlin/com/netguru/multiplatform/charts/pie/PieChartConfig.kt +++ b/charts/src/commonMain/kotlin/com/netguru/multiplatform/charts/pie/PieChartConfig.kt @@ -27,6 +27,7 @@ data class PieChartConfig( val legendIconSize: Dp = PieDefaults.LEGEND_ICON_SIZE, val legendOrientation: LegendOrientation = LegendOrientation.HORIZONTAL, val numberOfColsInLegend: Int = PieDefaults.NUMBER_OF_COLS_IN_LEGEND, + val showPercentages: Boolean = false ) enum class LegendIcon {