Reputation: 23
I am trying to create a bar graph similar to the one below - where the x axis has 2 different labels - one the labels on the bars themselves, indicating performance, and the other at the bottom of the axis, indicating the year. Only the numbers need to be shown rotated, on the graph rather than at the top.
I am showing the years by creating custom labels. I am also able to show the performance figures for the bars by implementing the -dataLabelForPlot:recordIndex:
method. The performance figures shows up but horizontally, but I want to be able to rotate the performance figures by 90 degrees.
Setting the labelRotation
on the plot does not help because I have set the labelingPolicy
to CPTAxisLabelingPolicyNone
so I can add custom labels.
Below is my code:
-(CPTLayer *)dataLabelForPlot:(CPTPlot *)plot recordIndex:(NSUInteger)index
{
CPTMutableTextStyle *axisTitleTextStyle = [CPTMutableTextStyle textStyle];
axisTitleTextStyle.fontSize = 10.0;
axisTitleTextStyle.color = [CPTColor blackColor];
CPTTextLayer *label = [[CPTTextLayer alloc] init];
label.textStyle = axisTitleTextStyle;
if ( [plot isKindOfClass:[CPTBarPlot class]] ) {
if ( [plot.identifier isEqual:@"Fund"] ) {
label.text = [[[self dataGroup1] objectAtIndex:index] stringValue];
}
else if ( [plot.identifier isEqual:@"Benchmark"] ) {
label.text = [[[self dataGroup2] objectAtIndex:index] stringValue];
}
}
return [label autorelease];
}
- (void) drawGraph
{
graphHostingView_ = [[CPTGraphHostingView alloc] initWithFrame:self.bounds];
calPerfGraph_ = [[CPTXYGraph alloc] initWithFrame:self.bounds];
graphHostingView_.hostedGraph = calPerfGraph_;
[self addSubview:graphHostingView_];
calPerfGraph_.plotAreaFrame.masksToBorder = NO;
calPerfGraph_.paddingLeft = 5.0;
calPerfGraph_.paddingTop = 20.0;
calPerfGraph_.paddingRight = 10.0;
calPerfGraph_.paddingBottom =20.0;
calPerfGraph_.plotAreaFrame.paddingTop = 10.0;
calPerfGraph_.plotAreaFrame.paddingBottom = 50.0;
calPerfGraph_.plotAreaFrame.paddingLeft = 10.0;
calPerfGraph_.plotAreaFrame.paddingRight = 35.0;
// Y axis scale - round to nearest ten
int maxYScale = (([[self getPositiveMax] intValue] / 10 ) + 1) * 10;
int minYScale = (([[self getNegativeMax] intValue] / 10 ) + 1) * 10;
// Styles
CPTMutableLineStyle *lineStyle = [CPTMutableLineStyle lineStyle];
lineStyle.lineColor = [CPTColor grayColor];
lineStyle.lineWidth = 2.0f;
CPTMutableLineStyle *gridLineStyle = [CPTMutableLineStyle lineStyle];
gridLineStyle.lineColor = [CPTColor grayColor];
gridLineStyle.lineWidth = 1.0f;
// X axis
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)calPerfGraph_.axisSet;
axisSet.xAxis.minorTicksPerInterval = 0;
axisSet.xAxis.majorTickLineStyle = lineStyle;
axisSet.xAxis.axisLineStyle = lineStyle;
axisSet.xAxis.majorTickLength = 0;
axisSet.xAxis.labelingPolicy = CPTAxisLabelingPolicyNone;
axisSet.xAxis.axisConstraints = [CPTConstraints constraintWithLowerOffset:0]; // Bring labels to the bottom on the plot
axisSet.xAxis.labelRotation = M_PI/2;
int currentYear = [self getCurrentYear];
NSMutableArray *customLabels = [NSMutableArray arrayWithCapacity:6];
for (int i=currentYear-5,count=1; currentYear>=i; i++,count++) {
CPTAxisLabel *newLabel = [[CPTAxisLabel alloc] initWithText:[NSString stringWithFormat:@"%d",i] textStyle:axisSet.xAxis.labelTextStyle];
newLabel.tickLocation = CPTDecimalFromInt(count);
newLabel.offset = axisSet.xAxis.labelOffset + axisSet.xAxis.majorTickLength;
[customLabels addObject:newLabel];
[newLabel release];
}
axisSet.xAxis.axisLabels = [NSSet setWithArray:customLabels];
// Y axis
if ( maxYScale >= 40 || minYScale >= 40) {
axisSet.yAxis.majorIntervalLength = [[NSDecimalNumber decimalNumberWithString:@"20"] decimalValue];
}
else {
axisSet.yAxis.majorIntervalLength = [[NSDecimalNumber decimalNumberWithString:@"10"] decimalValue];
}
axisSet.yAxis.minorTicksPerInterval = 0;
axisSet.yAxis.majorTickLength = 0;
axisSet.yAxis.majorGridLineStyle = gridLineStyle;
axisSet.yAxis.axisLineStyle = nil;
axisSet.yAxis.axisConstraints = [CPTConstraints constraintWithUpperOffset:0]; // Bring labels to the right end of the plot
axisSet.yAxis.tickDirection = CPTSignPositive;
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)calPerfGraph_.defaultPlotSpace;
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(0.0) length:CPTDecimalFromDouble([[self calPerfFundData] count]+1)];
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(-minYScale) length:CPTDecimalFromDouble(minYScale + maxYScale)];
CPTBarPlot *barPlot = [CPTBarPlot tubularBarPlotWithColor:[CPTColor greenColor] horizontalBars:NO];
barPlot.baseValue = CPTDecimalFromString(@"0");
barPlot.dataSource = self;
barPlot.barOffset = CPTDecimalFromFloat(.7);
barPlot.identifier = @"Fund";
barPlot.barWidth = CPTDecimalFromFloat(.25);
[barPlot addAnimation:[self animateVerticalBars] forKey:@"FundAnimation"];
[calPerfGraph_ addPlot:barPlot toPlotSpace:plotSpace];
CPTBarPlot *bbarPlot = [CPTBarPlot tubularBarPlotWithColor:[CPTColor colorWithComponentRed:0.9 green:0.9 blue:0.9 alpha:0.8] horizontalBars:NO];
bbarPlot.baseValue = CPTDecimalFromString(@"0");
bbarPlot.dataSource = self;
bbarPlot.barOffset = CPTDecimalFromFloat(1);
bbarPlot.barWidth = CPTDecimalFromFloat(.25);
bbarPlot.identifier = @"Benchmark";
[bbarPlot addAnimation:[self animateVerticalBars] forKey:@"BenchmarkAnimation"];
[calPerfGraph_ addPlot:bbarPlot toPlotSpace:plotSpace];
}
How can I rotate the performance figures on the bars? Any help is appreciated. Thanks.
Upvotes: 2
Views: 2389
Reputation: 27381
Both plots and axes have their own independent labelRotation
properties. You will be responsible for setting the rotation of your custom axis labels, but the labelRotation
property of the bar plot should set the rotation for the data labels above the bars.
Upvotes: 3