问题
I'm using ios-charts. I want to create a pie chart like below image. I have done all the confings, but I have problem with adding the image in the circle beside the values outside the circle.
Can anybody help me how to to add the circles and image inside it ?
UPDATED: note that the pie chart will scroll and those images should scroll with the related slices.
UPDATED: I used @Aditya Garg sample code to draw images beside the position of labels, and my chart is now looks like this :
I set the imageViewFrame like this:
imageView.frame = CGRect(x: xPos-10, y: yPos+10, width: 20, height: 20)
UPDATED: Github Pull request for ios-chart repo swift
回答1:
Setting the circle and the image inside is easy. First create a UIImageView, change the corner radius, and put the image inside
//Assuming you have declared a UIImageView and an image
imageView.layer.cornerRadius = imageView.frame.size.width/2
imageView.clipsToBounds = true
imageView.image = image
You can create as many of these as you need programmatically
func drawCircle(xPos:CGFloat, yPos:CGFloat, name: String){
let image = UIImage(named: name)
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: xPos-10, y: yPos+10, width: (image?.size.width)!, height: (image?.size.height)!)
imageView.layer.cornerRadius = imageView.frame.size.width/2
imageView.clipsToBounds = true
imageView.tag = 1000 //this is so we can later remove and redraw the circle in a new position
pieChart.addSubview(imageView)
}
The trickier part is drawing these images at the correct place (the circle image is always aligned with the middle of the pie chart section). You have to calculate the angle between these sections manually, and then add in the UImageView we created to this position
These are the geometric properties that pieChart exposes to us
let FDEG2RAD = CGFloat(M_PI / 180.0)
var absoluteAngles : [CGFloat] = pieChart.absoluteAngles
absoluteAngles.insert(0, at: 0)
var center = pieChart.centerCircleBox
center.x = center.x - 15 //correction factor for center, adjust these as you see fit
center.y = center.y - 11
let r: CGFloat = pieChart.radius + 30 //distance from center
Where absolute angles is an array of the slice angles. These always get bigger and end at 360 degrees. Note that we manually insert 0 at the beginning so that the code works nicely.
There is a bug where centerCircleBox does not return the true center. To fix this use this function to draw an image on where the pieChart says its center is and then adjust the correction factor to get it in the true center. (make sure to add a smallish image file to your project, i used a red x mark)
func drawCenterX(xPos:CGFloat, yPos:CGFloat){
let xred = "xmarks.png"
let image = UIImage(named: xred)
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: xPos, y: yPos, width: (image?.size.width)!, height: (image?.size.height)!)
pieChart.addSubview(imageView)
}
For the math, we simply have to keep track of our last absolute angle, our current absolute angle and find the angle in between. Add this onto our last value to find the true angle and then convert to X,Y coordinates. Note that the larger the Y gets, the more down the screen it goes, so we have to subtract not add.
let x = center.x + (r * sin((absoluteAngles[last] + ((absoluteAngles[current] - absoluteAngles[last] )/2)) * FDEG2RAD))
let y = center.y - (r * cos((absoluteAngles[last] + ((absoluteAngles[current] - absoluteAngles[last] )/2)) * FDEG2RAD))
Now, just iterate through the absoluteAngles array, calculate the position, and place the UIImageView here. See the full code below
func setLabels(vals : [Int]){
let subViews = self.pieChart.subviews //this removes the previous UIImageViews
for subview in subViews{
if subview.tag == 1000 {
subview.removeFromSuperview()
}
}
let FDEG2RAD = CGFloat(M_PI / 180.0)
var absoluteAngles : [CGFloat] = pieChart.absoluteAngles
absoluteAngles.insert(0, at: 0)
var center = pieChart.centerCircleBox
center.x = center.x - 15 //correction factor for center, adjust these as you see fit
center.y = center.y - 11
let r: CGFloat = pieChart.radius + 30 //distance from center
var current = 1
var last = 0
for value in vals{
let x = center.x + (r * sin((absoluteAngles[last] + ((absoluteAngles[current] - absoluteAngles[last] )/2)) * FDEG2RAD))
let y = center.y - (r * cos((absoluteAngles[last] + ((absoluteAngles[current] - absoluteAngles[last] )/2)) * FDEG2RAD))
last = current
current = current + 1
UIView.animate(withDuration: 1.0, delay: 0, options: .curveEaseOut, animations: { //Adds a nice animation that brings the circle in from off screen
//Implement your own logic for how you want to pass in the name of the section to the function we defined above.
self.drawCircle(xPos: x, yPos: y, name: name)
}, completion: nil)
}
drawCenterX(xPos: center.x, yPos: center.y)//visually locate center
}
Let me know if you have any questions!
来源:https://stackoverflow.com/questions/42113512/add-an-image-for-each-slice-in-ios-chart-piechart