Hello, I am drawing a chart and trying to place a ...
# compose
n
Hello, I am drawing a chart and trying to place a snippet on top of each arc but but next arc overlaps the snippet of previous one. How can I make all snippets being on top of the whole chart? Code in thread
👀 1
Sorry for some math here. But you can ignore and focus on Canvas methods 🙂
Copy code
``````partitions.forEach { partition ->
val sweepAngle = partition.sweepAngle

// Draw Circle
drawArc(
startAngle = startAngle,
sweepAngle = sweepAngle,
size = arcSize,
progressBrush = partition.style,
strokeWidthInPx = progressStrokeWidthInPx
)

// Draw Snippet
val snippet = partition.snippet
if (snippet != null) {
val snippetText = snippet.text
val snippetBackground = snippet.background

val textWidth = snippetText.rect.width()
val textHeight = snippetText.rect.height()

val angleMidpoint = startAngle + (sweepAngle / 2)

val snippetWidth = textWidth + (padding * 2)
val snippetHeight = textHeight + (padding * 2)

// Find polar coordinates of snippet center and convert them to cartesian coordinates
// A great source for learning about coordinates: <https://varun.ca/polar-coords/>
val snippetCenterXCoordinate =
val snippetCenterYCoordinate =
centerY + (((progressStrokeWidthInPx + snippetHeight) / 2) + radius) * sin(
)
// Calculate the snippet so it is drawn based on its center points
val snippetXCoordinate = snippetCenterXCoordinate - (snippetWidth / 2)
val snippetYCoordinate = snippetCenterYCoordinate - (snippetHeight / 2)

val textXCoordinate = snippetXCoordinate + padding
val textYCoordinate = snippetYCoordinate + textHeight + padding

// Snippet background stroke
val snippetStroke = snippetBackground.stroke
if (snippetStroke != null) {
drawRoundRect(
brush = snippetStroke.style,
x = snippetXCoordinate,
y = snippetYCoordinate,
width = snippetWidth,
height = snippetHeight,
style = Stroke(width = snippetStroke.widthInPx),
)
}

// Snippet background fill
drawRoundRect(
brush = snippetBackground.style,
x = snippetXCoordinate,
y = snippetYCoordinate,
width = snippetWidth,
height = snippetHeight,
style = Fill,
)

drawLine(
Color.Red,
start = Offset(centerX, centerY),
end = Offset(textXCoordinate, textYCoordinate)
)
drawLine(
Color.Green,
start = Offset(centerX, centerY),
end = Offset(snippetCenterXCoordinate, snippetCenterYCoordinate)
)

// Snippet text
drawText(
x = textXCoordinate,
y = textYCoordinate,
value = snippetText.value,
style = snippetText.style
)
}

startAngle += sweepAngle
}``````
o
You should draw all your
``arcs``
in one for-each and snippets in another one, so that all snippets are drawn “after” all
``arc``
segments.
n
Thanks @Oleksandr Balan yeah I know that’s one solution but can I achieve the same using BlendMode or something like this?
z
Im actually working on something similar myself! I havent really figured out a perfect approach yet, but my thinking is that you could use the previous snippets location to determine the offset for the current one (if any). That by itself will probably look awkward since it always pushes them to the right, but you could follow the same practice to figure out which ones will overlap, and then push the previous one 50% to the left, and the current one 50% to the right. Hope that makes sense 😅 In theory that should work unless Im missing something fundamental.
n
Thanks, that sounds a bit more complex than having 2 for each loops 😄 For now I went for 2 for each but thanks for the heads up, I’ll deffo consider 🙂
z
Yeah Im hoping for a simpler solution as well, but its really not that complicated when you think about it! I guess Ill see once I get back to working on this myself 😁 Does two for loops work? I understand that theyre drawn at the end of each slice that way, but in your picture the slices end so close to each other - Id think that theyre still drawn on top of each other?
Oh, whoops. Ill just.. homer disappear