我正在尝试绘制带有各个部分的饼图并显示每个部分的标签。标签应显示在每个部分的开头,并与饼图保持 10dp 的间距。
这是我的代码:
@Composable
fun PieChartLocal(
modifier: Modifier = Modifier,
width: Float,
thickness: Float,
duration: Int,
sections: List<Section>,
) {
val sweepAngles = remember(sections) { findSweepAngles(sections) }
val animateFloat = remember { Animatable(0f) }
val density = LocalDensity.current
val paddingDp = 18.dp
val textSizeDp = 10.sp
val paddingPx = with(density) { paddingDp.toPx() }
val textSizePx = with(density) { textSizeDp.toPx() }
LaunchedEffect(animateFloat) {
animateFloat.animateTo(
targetValue = 1f,
animationSpec = tween(durationMillis = duration, easing = LinearEasing)
)
}
Canvas(
modifier = modifier
.size((width + 2 * (paddingDp.value + textSizeDp.value)).dp)
) {
var startAngle = 0f
val radius =
(size.minDimension - 2 * (paddingPx + textSizePx)) / 2
val center = size.center
for (i in sweepAngles.indices) {
val sweepAngle = sweepAngles[i] * animateFloat.value
val color = sections[i].color
drawArc(
color = color,
startAngle = startAngle,
sweepAngle = sweepAngle,
useCenter = false,
style = Stroke(width = thickness),
topLeft = Offset(center.x - radius, center.y - radius),
size = Size(radius * 2, radius * 2),
)
val angleInRadians = Math.toRadians(startAngle.toDouble())
val textRadius = radius + paddingPx
val x = center.x + textRadius * cos(angleInRadians).toFloat()
val y = center.y + textRadius * sin(angleInRadians).toFloat()
val percentage = (sweepAngles[i] / ROUND_ANGLE * 100).toInt()
drawContext.canvas.nativeCanvas.apply {
drawText(
"$percentage%",
x,
y,
TextPaint().apply {
textAlign = Paint.Align.CENTER
textSize = textSizePx
}
)
}
startAngle += sweepAngle
}
}
}
private fun findSweepAngles(sections: List<Section>): List<Float> {
val values = sections.map(Section::value)
val sumValues = values.sum()
return values.map { value -> ROUND_ANGLE * value / sumValues }
}
问题是,对于某些标签,我的饼图偏移量不正确。对于许多标签,它等于预期的 10dp,而对于其余标签,它完全不存在。可能是什么问题?
请帮我..
您可以参考这个答案来绘制一个饼图,其中每个部分的中心都有文本。
当您希望在段的开头绘制文本时,可以使用如下公式
textOffset 是我们用来根据文本矩形从文本边界左上角偏移的。
在我们的例子中,偏移量是额外的用户偏移量,10.dp 外半径是图表,它是下面 gif 中的蓝色圆圈。
在 gif 中,文本位于线段下方的原因是我将圆弧和线段画在一起。如果它们要相交,请在另一个循环中绘制文本
文本矩形的左上角指向每个段的起点。下一步是更改每个象限的矩形中段的起始位置应接触的位置。
添加
取消注释注释片段后的结果