add an image for each slice in iOS-chart pieChart

假装没事ソ 提交于 2019-12-10 10:44:01

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!