0
votes

I'm using CorePlot to draw PieChart. I would like to display labels for slices on slices themselves. Is there a way to get coordinates of each slice and then setting the frame of CPTLayer that holds the text label to adjust to coordinates of the slice?

What I am doing so far:

-(CPRLayer*) datLabelForPlot(CPTPlot*)plot recordIndex:(NSUInteger)index {
  static CPTMutableTextStyle *textStyle = nil;
  NSString *string = @"Test";

    if ( !textStyle) {
        textStyle= [[CPTMutableTextStyle alloc] init];
        textStyle.color = [CPTColor whiteColor];
    }
    CPTLayer *layer = [[[CPTLayer alloc] initWithFrame:CGRectMake(50,50, 100, 20)]autorelease];
    CPTTextLayer *newLayer = nil;
    newLayer = [[[CPTTextLayer alloc] initWithText:string style:textStyle] autorelease];
    [layer addSublayer:newLayer];
    return layer;
}

but regardless of the layer frame, label is always displayed at the same position (outside the chart). How to set the appropriate layer frame to display the text on the slice itself?

Here is the image of the points I would like to know: piechart

2
Could you describe what you mean by the "coordinates of each slice"? - Eric Skroch
here is the image: dl-web.dropbox.com/get/Public/piechart.png?w=611f0ec7 I would like to know the coordinates for centre of the pie, as well as points A and B, so I can position my label somewhere in between those 3 points. - Maggie
That link doesn't have public permissions. Can you describe where A and B are? - Eric Skroch
I've updated the question with the image. - Maggie

2 Answers

3
votes

Have you tried setting the CPPieChart labelOffset property to a negative value? May be it doesn't provide the level of precision that you need, but it's an easy solution.

Positive Offset:

Positive Offset

Negative Offset:

enter image description here

0
votes

The centerAnchor is expressed as a fraction of the size of the plot area, so you can use the following code to compute its pixel position (point "O" on your picture):

CPTPieChart *pieChart; // the pie chart
CGRect plotAreaBounds = pieChart.plotArea.bounds;
CGPoint anchor = pieChart.centerAnchor;
CGPoint centerPoint = CGPointMake(plotAreaBounds.origin.x + plotAreaBounds.size.width * anchor.x,
                                  plotAreaBounds.origin.y + plotAreaBounds.size.height * anchor.y);

You can look at the Core Plot source code to see how the pie chart computes the positions of the labels. This code accounts for slices that are "exploded" and centers the label between what you called points "A" and "B", offset by the labelOffset. It hides the label if the datasource returned a missing value (NAN) for the slice. The index corresponds to the datasource index of the pie slice. The relevant bits are:

double currentWidth = [self cachedDoubleForField:CPTPieChartFieldSliceWidthNormalized recordIndex:index];
if ( isnan(currentWidth) ) {
    contentLayer.hidden = YES;
}
else {
    id<CPTPieChartDataSource> theDataSource = id<CPTPieChartDataSource>)self.dataSource;
    BOOL dataSourceProvidesRadialOffsets = [theDataSource respondsToSelector:@selector(radialOffsetForPieChart:recordIndex:)];
    CGFloat radialOffset = 0.0;
    if ( dataSourceProvidesRadialOffsets ) {
        radialOffset = [theDataSource radialOffsetForPieChart:self recordIndex:index];
    }

    CGFloat labelRadius = self.pieRadius + self.labelOffset + radialOffset;

    double startingWidth = 0.0;
    if ( index > 0 ) {
        startingWidth = [self cachedDoubleForField:CPTPieChartFieldSliceWidthSum recordIndex:index - 1];
    }
    CGFloat labelAngle = [self radiansForPieSliceValue:startingWidth + currentWidth / (CGFloat)2.0];

    label.displacement = CGPointMake( labelRadius * cos(labelAngle), labelRadius * sin(labelAngle) );
    contentLayer.hidden = NO;
}