I created a simple pie chart on Swift that looks like this: Current state
But now I need to add text inside each pie section like this: Expected result
and I'm not sure how to accomplish that.
This is the code I used to create the graph
override func draw(_ rect: CGRect) {
let ctx = UIGraphicsGetCurrentContext()
let radius = min(frame.size.width, frame.size.height) * 0.5
let viewCenter = CGPoint(x: bounds.size.width * 0.5, y: bounds.size.height * 0.5)
let valueCount = segments.reduce(0, {$0 + $1.value})
var startAngle = -CGFloat.pi * 0.5
for segment in segments {
ctx?.setFillColor(segment.color.cgColor)
let endAngle = startAngle + 2 * .pi * (segment.value / valueCount)
ctx?.move(to: viewCenter)
ctx?.addArc(center: viewCenter, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: false)
ctx?.fillPath()
startAngle = endAngle
}
}
I created labels for each section, but I'm not sure how to calculate the frame position or if there's a property in the context that could help me to place them inside each section like in the image above. I tried using the startAngle/endAngle as a starting point but they just stack one on top of another.
The trick is to first calculate the center of where each segment's label should be positioned. A little trigonometry gives you:
where
midAngleis the centerline of each segment (halfway between the start and end angles). The0.75is the percentage of the radius you want the text to be from the center of the circle. Adjust as desired.Then you need to figure out the bounding box of the text to be drawn for a given segment and then adjust that based on the calculated center.
Finally you can draw the text.
Here is a version of your code that can be run in an iOS Swift Playground. I guessed at the
Segmentstruct based on your code. What I show below is enough to make it run.This gives you the following:
Some of the text methods (
boundingRectanddraw) come fromNSStringwhich are convenient methods for drawing into a CGContext. Easier than the text drawing methods found inCGContext.