Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow PieChartView to hide labels for tiny slices #944

Closed
wants to merge 3 commits into from

Conversation

rofreg
Copy link
Contributor

@rofreg rofreg commented Apr 12, 2016

Right now, if you have a labelled pie chart with a large number of tiny sections, the labels are very likely to overlap in a visually unappealing way. This commit adds a basic property to auto-hide labels for any pie chart section below a certain size – e.g. only show pie chart labels for pie sections that span at least 20º.

I also updated the color of the labels in the PieChart demo from white to black for legibility.

Before:
screen shot 2016-04-12 at 11 58 33 am

After:
screen shot 2016-04-12 at 11 58 29 am

@@ -25,6 +25,7 @@ public class PieChartView: PieRadarChartViewBase
private var _circleBox = CGRect()

private var _drawXLabelsEnabled = true
private var _drawXLabelsMinimumAngle: Double = 0

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use CGFloat

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! I could have sworn that I used a Double here for a reason, but I can't remember that reason now, so I've switched it to a CGFloat.

@DingSoung
Copy link

This is not a good solution, as some big slices have short x value string(should display), and some small slice have long x value (should hide), a specific value of angle could not determine this.

@danielgindi
Copy link
Collaborator

@DingSoung I would say "it's not the perfect solution", not necessarily not a "good" one.
@rofreg Some more magic needs to be put in there.

@rofreg
Copy link
Contributor Author

rofreg commented May 3, 2016

@danielgindi Do you have any recommendations on how to make it more magic? I did try a few solutions that were more intricate, but in the end I thought it was best to keep this simple. (For my purposes, the most important thing was to hide the labels for a series of extremely small slices, each around 1% of the pie or less – they were all showing up on top of each other in a garbled mess. Not sure how common that is for other people.)

A few things I considered:

  • Should X labels be allowed to extend beyond the bounds of the pie slice? Right now they can, and I figured that was more of a feature than a bug. Filtering by slice size seemed like an elegant way to hide less important labels (assuming that smaller pie segments are less important), while still allowing labels of any size.
  • Alternately, should X labels only be shown if they fit entirely inside the pie slice? If so, then code would need to account for the size of the text, the size of the pie slice, and the specific rotation angle of the pie slice. (e.g. A pie slice of 10º might be able to display a long label if it's horizontal, but not if it's vertical.) That seemed like overkill when I was mainly trying to hide labels for ultra-small slices, but I could potentially revisit that.
  • If an X label is too large to be displayed, should it be truncated instead of hidden? That seemed like a separate setting to me, so I left it out.

Let me know if you have thoughts on any of those possibilities!

@DingSoung
Copy link

DingSoung commented May 4, 2016

@danielgindi @rofreg
I have tried, here is effect
screen shot 2016-05-04 at 2 22 28 pm

step:
1 add a Bool property for PieChartView

    private var _limitXLableSizeInSlice: Bool = false
    public var limitXLableSizeInSlice: Bool {
        get {
            return _limitXLableSizeInSlice
        }
        set {
            _limitXLableSizeInSlice = newValue
            setNeedsDisplay()
        }
    }

2 in drawValues of PieChartRenderer, check before draw, example

                    else if drawXInside
                    {
                        let attributes = [NSFontAttributeName: valueFont, NSForegroundColorAttributeName: dataSet.valueTextColorAt(j)]
                        let size = data.xVals[j]!.sizeWithAttributes(attributes)

                        if chart.limitXLableSizeInSlice == true
                            && size.width > labelRadius * sliceAngle * ChartUtils.Math.FDEG2RAD {

                        } else {
                            ChartUtils.drawText(
                                context: context,
                                text: data.xVals[j]!,
                                point: CGPoint(x: x, y: y + lineHeight / 2.0),
                                align: .Center,
                                attributes: attributes
                            )
                        }
                    }

I do this in subClass and used particular configuration, some more need be considered (with hole or not, show y value or not etc.)

@rofreg
Copy link
Contributor Author

rofreg commented Jun 1, 2016

@DingSoung
Thanks for the code sample! :) I definitely see the appeal of that approach, though there are limitations on basing it on labelRadius * sliceAngle * ChartUtils.Math.FDEG2RAD:

  • The label will still appear in some situations where it is too large
    too-big
  • The label will not appear in some situations where it would actually fit
    too-small

We could potentially do more advanced math to figure out the actual maximum size (calculating the largest box that could fit in the center of the pie slice, then hiding the label if it doesn't fit in that box), but that seemed like overkill to me, at least for the application where I used this code. The main goal I wanted to achieve was to hide labels for insignificant pie slices (e.g. sections that only make up 1% of the pie), in order to filter out "less important" parts of the data set and highlight the larger pie slices.

@rofreg
Copy link
Contributor Author

rofreg commented Jul 7, 2017

I'm closing this in favor of #2062, which appears to reimplement the same improvements in Swift 3.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants