PieChart Legend Customization


#1

1- how to make the pie chart legend with fixed width not flexible?

 

2 - how  to change the legend items (symbols) colors and make its titles aligned to left or right not center ??

 

thanks so much


Swift : Set content inside legend in Shinobi Donut
#2
  1. The legend is a UIView and so you can manage its frame yourself if you wish to (you can access it via the chart’s legend property).
  2. The symbols can be changed by adopting the SChartLegendItem protocol.  All SChartSeries already do this by default so you can just subclass one of those and override the methods as appropriate to alter the symbols or titles.

Hope that’s useful!


#3

working not for me…  :slight_frown:

My NSLog (after adding the chart to the view) from the chart mainframe  is: x: 15.000000 y: 47.000000 w: 576.000000 h: 300.000000
and from the legend (via theChart.legend.frame) : x: 0.000000 y: 0.000000 w: 0.000000 h: 0.000000 (but i see the legend)
placment and position are: SChartLegendPlacementOutsidePlotArea and SChartLegendPositionMiddleRight.
I need a margin between chart and legend by 15 px. 

How i create the chart and legend:

- (SChartLegend*)createLegend{
    
    SChartLegendStyle *lStyle = [[[SChartLegendStyle alloc] init] autorelease];
    [lStyle setTextAlignment:NSTextAlignmentLeft];
    [lStyle setFont:[UIFont fontWithName:@"UniversLTStd-Light" size:12.0]];
    [lStyle setFontColor:[UIColor blackColor]];
    [lStyle setShowSymbols:YES];
    [lStyle setSymbolAlignment:SChartSeriesLegendAlignSymbolsLeft];
    
    SChartLegend *legend = [[[SChartLegend alloc] initWithChart:theChart] autorelease];
    [legend setAutosizeLabels:NO];
    [legend setStyle:lStyle];
    [legend setPlacement:SChartLegendPlacementOutsidePlotArea];
    [legend setPosition:SChartLegendPositionMiddleRight];
    [legend setClipsToBounds:YES];
    
    return legend;
}

- (void)initShinobiWithDefaultsAndFrame:(CGRect)frame{
    

    theChart = [[ShinobiChart alloc] initWithFrame:frame];
    [theChart setLicenseKey:DEK_SHINOBI_LIZENZ_KEY];
    [theChart setDelegate:self];
    [theChart setAutoresizingMask:UIViewAutoresizingNone];
    
    [theChart setGesturePanType:SChartGesturePanTypePanPinch]; 
    [theChart setGestureDoubleTapEnabled:YES];
    [theChart setGestureDoubleTapResetsZoom:YES];
    [theChart setGesturePinchAspectLock:NO];
    
    [theChart setAnimateBoxGesture:YES];
    [theChart setAnimateZoomGesture:YES];
    
    [theChart setRadialTapEnabled:YES];
    [theChart setRadialRotationEnabled:YES];
    
    [theChart setLegend:[self createLegend]];
    
    [theChart setClipsToBounds:YES];
    
    [theChart setBackgroundColor:[UIColor whiteColor]];
    [theChart setPlotAreaBackgroundColor:[UIColor whiteColor]];
    
}

#4

and one think… setFrame on theChart.canvas or theChart.canvas.glView has no effect. When i change the frame of the Legend the chart is drawn in full size.


#5

my solution for this issue is (but oi think this is not the best way):

- (void)sChartRenderFinished:(ShinobiChart*)chart{    
/*
    firstDrawFinished is set to NO in:
    - toggledSelectionForSeries:
    - toggledSelectionForPoint:
*/
    if(firstDrawFinished==NO){
        
        for(UILabel *lan in theChart.legend.labels){
            [lan setFrame:CGRectMake(20,lan.frame.origin.y,lan.frame.size.width-10,lan.frame.size.height)];
        }

        for(SChartLegendSymbol *sym in theChart.legend.symbols){
           if(![sym isKindOfClass:[SChartLegendSymbolDonutSeries class]] || ![sym isKindOfClass:[SChartLegendSymbolPieSeries class]]) [sym setFrame:CGRectMake(5,sym.frame.origin.y+2,sym.frame.size.width,sym.frame.size.height-10)];
           else [sym setFrame:CGRectInset(sym.frame, 5, sym.frame.origin.y)];
        }
        firstDrawFinished = YES;
    }
}

#6

Hi Mirko,

In order to add a margin between the chart and the legend, you can use the marginWidth property on the legend style.  This is specified in pixels, so you should be able to achieve the effect you’re looking for.  I would try adding the following line when creating your legend:

legend.style.marginWidth = @(15.f);

Let me know if that helps!

Regards,

Dan


#7

Hey Dan,

i have tested your soltuion and it works fine. Big thanks.


#8

i have started implimenting pie chart but getting errors of xAxis  not set ,i fond your tutorial for pie chart in which also but i cant find declairation of Axis over there?

 - (void)viewDidLoad {
    [super viewDidLoad];
    mobileOSVersions = [MobileOSVersions new];
    datasource = [Datasource new];
    datasource.osData = mobileOSVersions;
    NSString *licenseKey = @“R+pigi98m+sHlGaMjAxNDEyMjR2aXJhbDg1QGdtYWlsLmNvbQ==Y6wCCupER1nzgTLwM1I64RnX7rgJlvSkU3e3N7YuLLqPDr70OtZDKVjc/a4tMDyR6z0HTtfCyk2nKQZqCBkqVJkC0TEvlx2vRws5XC3OqRySv+AlrhbMf8Pab9c8FbWpLpbe751fBTfsde1uw7GiE37wIEo0=BQxSUisl3BaWf/7myRmmlIjRnMU2cA7q+/03ZX9wdj30RzapYANf51ee3Pi8m2rVW6aD7t6Hi4Qy5vv9xpaQYXF5T7XzsafhzS3hbBokp36BoJZg8IrceBj742nQajYyV7trx5GIw9jy/V6r0bvctKYwTim7Kzq+YPWGMtqtQoU=PFJTQUtleVZhbHVlPjxNb2R1bHVzPnh6YlRrc2dYWWJvQUh5VGR6dkNzQXUrUVAxQnM5b2VrZUxxZVdacnRFbUx3OHZlWStBK3pteXg4NGpJbFkzT2hGdlNYbHZDSjlKVGZQTTF4S2ZweWZBVXBGeXgxRnVBMThOcDNETUxXR1JJbTJ6WXA3a1YyMEdYZGU3RnJyTHZjdGhIbW1BZ21PTTdwMFBsNWlSKzNVMDg5M1N4b2hCZlJ5RHdEeE9vdDNlMD08L01vZHVsdXM+PEV4cG9uZW50PkFRQUI8L0V4cG9uZW50PjwvUlNBS2V5VmFsdWU+”;
    CGRect donutFrame;
    donutFrame = CGRectMake(self.view.bounds.size.width/2+25,150,self.view.bounds.size.width/2-50,700);
    DonutChart = [ShinobiChart donutChartForOSVersionDataWithFrame:donutFrame];
    DonutChart.title = @“Versions of OS currently in use”;
    
    
    
    DonutChart.licenseKey = licenseKey;
    
    datasource.donutChart = DonutChart;
    DonutChart.datasource = datasource;
    lineView = [[LineView alloc] init];
    [lineView setUserInteractionEnabled:NO];
    [lineView setBackgroundColor:[UIColor clearColor]];
    [DonutChart addSubview:lineView];
    
    
    //we setup a delegate to modify our labels
    DonutChart.delegate = self;
    [self.view addSubview:DonutChart];
    
//    lineView = [[LineView alloc] init];
//    [lineView setUserInteractionEnabled:NO];
//    [lineView setBackgroundColor:[UIColor clearColor]];
//    [pieChart addSubview:lineView];
    // Do any additional setup after loading the view, typically from a nib.
}
//-(void)sChart:(ShinobiChart *)chart alterLabel:(UILabel *)label forDatapoint:(SChartDataPoint *)datapoint atSliceIndex:(int)index inRadialSeries:(SChartRadialSeries*)series
//
//{
//    [label setText:datapoint.xValue];
//    [label sizeToFit];
//    [label setHidden:NO];
//    
//    return label;
//}

//-(void)sChart:(ShinobiChart *)chart alterLabel:(UILabel *)label forDatapoint:(SChartDataPoint *)datapoint atSliceIndex:(int)index inRadialSeries:(SChartRadialSeries *)series
//{
//    SChartPieSeries *pieSeries = (SChartPieSeries *)series;
//    
//    //get our radial point from our datasource method
//    
//    // three points:
//    CGPoint pieCenter;      // chart center for trig calculations
//    CGPoint oldLabelCenter; // original label center
//    CGPoint labelCenter;    // new label center
//    
//    pieCenter = [pieSeries getDonutCenter];
//    labelCenter = [pieSeries getSliceCenter:index];
//    
//    // find the angle of the slice, and add on a little to the label’s center
//    float xChange, yChange;
//    
//    xChange = pieCenter.x - labelCenter.x;
//    yChange = pieCenter.y - labelCenter.y;
//    
//    float angle = atan2f(xChange, yChange) + M_PI / 2.f;
//    // we do the M_PI / 2 adjustment because of how the pie is drawn internally
//    
//    labelCenter.x = labelCenter.x + EXTRUSION * cosf(angle);
//    labelCenter.y = labelCenter.y - EXTRUSION * sinf(angle);
//    
//    
//    [label setText:datapoint.xValue];
//    [label sizeToFit];
//    [label setCenter:labelCenter]; // this must be after sizeToFit
//    [label setHidden:NO];
//    
//
//   
//}

  • (void)sChartRenderFinished:(ShinobiChart *)chart {
        //For our first render make sure we animate our initial pie selection into place for effect :slight_smile:
        if (first && chart == DonutChart) {
            first = NO;
            [self performSelector:@selector(initialSelectionForChart:) withObject:chart afterDelay:0.1f];
        }
        
    }

  • (void)initialSelectionForChart:(ShinobiChart*)chart {
        SChartPieSeries *ps = (SChartPieSeries*)[chart.series lastObject];
        [ps setSlice:[datasource selectedSliceIndex] asSelected:YES];
        [chart redrawChartIncludePlotArea:YES];
    }

  • (void)sChart:(ShinobiChart *)chart toggledSelectionForRadialPoint:(SChartRadialDataPoint *)dataPoint inSeries:(SChartRadialSeries *)series atPixelCoordinate:(CGPoint)pixelPoint {
    //    if (chart == DonutChart && ([dataPoint.name isEqualToString:@“iOS”] || [dataPoint.name isEqualToString:@“Android”])) {
    //        
    //        SChartPieSeries *pieSeries = (SChartPieSeries*)series;
    //        
    //        for (int i=0; i<pieSeries.dataSeries.dataPoints.count; i++) {
    //            SChartDataPoint *dp = pieSeries.dataSeries.dataPoints[i];
    //            if (![[dp sChartXValue] isEqualToString:dataPoint.name]) {
    //                if (dataPoint.selected) {
    //                    [pieSeries setSlice:i asSelected:NO];
    //                }
    //            }
    //        }
        datasource.selectedOS = dataPoint.name;
        selectedOSLabel.text = datasource.selectedOS;
        
        [DonutChart reloadData];
        [DonutChart redrawChartIncludePlotArea:YES];
      //}
    }
    -(void)sChart:(ShinobiChart *)chart alterLabel:(UILabel *)label forDatapoint:(SChartDataPoint *)datapoint atSliceIndex:(int)index inRadialSeries:(SChartRadialSeries *)series {
        
        SChartPieSeries *pieSeries = (SChartPieSeries *)series;
        
        //get our radial point from our datasource method
        
        // three points:
        CGPoint pieCenter;      // chart center for trig calculations
        CGPoint oldLabelCenter; // original label center
        CGPoint labelCenter;    // new label center
        CGPoint endOfLine;     // we want our line to finish just short of our label
        
        pieCenter = [pieSeries getDonutCenter];
        oldLabelCenter = labelCenter = [pieSeries getSliceCenter:index];
        
        // find the angle of the slice, and add on a little to the label’s center
        float xChange, yChange;
        
        xChange = pieCenter.x - labelCenter.x;
        yChange = pieCenter.y - labelCenter.y;
        
        float angle = atan2f(xChange, yChange) + M_PI / 2.f;
        // we do the M_PI / 2 adjustment because of how the pie is drawn internally
        
        labelCenter.x = oldLabelCenter.x + EXTRUSION * cosf(angle);
        labelCenter.y = oldLabelCenter.y - EXTRUSION * sinf(angle);
        
        endOfLine.x = oldLabelCenter.x + (EXTRUSION-30.f) * cosf(angle);
        endOfLine.y = oldLabelCenter.y - (EXTRUSION-30.f) * sinf(angle);
        
        [label setText:datapoint.xValue];
        [label sizeToFit];
        [label setCenter:labelCenter]; // this must be after sizeToFit
        [label setHidden:NO];
        
        // connect our old label point to our new label
        [lineView addPointPair:oldLabelCenter second:endOfLine forLabel:label];
    }

  • (void) sChartRenderStarted:(ShinobiChart *)chart withFullRedraw:(BOOL)fullRedraw {
        // position our view over the top of the GL canvas
        CGRect glFrame = chart.canvas.glView.frame;
        glFrame.origin.y = chart.canvas.frame.origin.y;
        [lineView setFrame:glFrame];
        // remove the old point-pairs from the line view
        [lineView reset];
    }


#9

Hello Nitinumaretiya,

The pie chart shouldn’t need axes and thus shouldn’t be logging those errors. These errors should be harmless though, and if your chart is working as expected I’d say you’re safe to ignore them.

Either way, would you be able to send in a small sample application replicating this issue to info@shinobicontrols.com and reference this forum post? We’ll be able to take a look at it first hand and get back to you.

PS. If you’ve got any further information to add it would be great if you could create a new thread explaining your issue. That would help keep things seperate from this pre-existing forum post so there isn’t any confusion.

Thanks,
Jan Akerman