Search code examples
ioscore-plot

Multiple y axes with custom label in core plot


-(void)configureAxes {

CPTGraph* graph = self.hostView.hostedGraph;    
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *) graph.defaultPlotSpace;
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
CPTScatterPlot* plot = [[CPTScatterPlot alloc] initWithFrame:CGRectZero];
plot.dataSource = self;
[graph addPlot:plot toPlotSpace:graph.defaultPlotSpace];       

[plotSpace setXRange: [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat( 0 ) length:CPTDecimalFromFloat( 8 )]];
[plotSpace setYRange: [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat( 0 ) length:CPTDecimalFromFloat( 10 )]];

self.arrayData=[[NSMutableArray alloc] initWithObjects:@"A",@"B",@"C",@"D",@"10",@"20",@"E", nil];
self.arrayDataY=[[NSMutableArray alloc] initWithObjects:@"CP",@"BD",@"Test",@"Notes",@"CM",@"Day",@"97.7",@"97.8",@"97.9", nil];

CPTMutableLineStyle *yMajorGridLineStyle = [CPTLineStyle lineStyle];
yMajorGridLineStyle.lineCap = kCGLineCapRound;
yMajorGridLineStyle.lineColor = [CPTColor whiteColor];
yMajorGridLineStyle.lineWidth = 1.0;


CPTMutableLineStyle *lineStyle=[CPTLineStyle lineStyle];
lineStyle.lineColor=[CPTColor redColor];
lineStyle.lineWidth=2.0f;

CPTMutableLineStyle *lineStyle1=[CPTLineStyle lineStyle];
lineStyle1.lineColor=[CPTColor greenColor];
lineStyle1.lineWidth=2.0f;

CPTMutableLineStyle *lineStyle2=[CPTLineStyle lineStyle];
lineStyle2.lineColor=[CPTColor blackColor];
lineStyle2.lineWidth=1.0f;

CPTXYAxis *x          = axisSet.xAxis;

NSMutableArray  *labelTick=[[NSMutableArray alloc] initWithObjects:@"1",@"2",@"3",@"4",@"5",@"6", nil];
x.labelingPolicy = CPTAxisLabelingPolicyNone;
x.majorIntervalLength= CPTDecimalFromInteger(1);
x.minorTicksPerInterval = 0;
x.majorTickLineStyle = lineStyle;
x.minorTickLineStyle = lineStyle1;
x.axisLineStyle = lineStyle2;
x.minorTickLength = 2.0f;
x.majorTickLength = 3.0f;
x.orthogonalCoordinateDecimal=CPTDecimalFromDouble(0.0);
x.majorTickLocations=[NSSet setWithArray:labelTick];
x.visibleRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0) length:CPTDecimalFromFloat([arrayDataY count])];
x.gridLinesRange=[CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat( 0 ) length:CPTDecimalFromFloat( [arrayDataY count] )];
x.labelOffset=30.0f;
x.majorGridLineStyle = yMajorGridLineStyle;
CGFloat dateCount = [self.arrayData count];
NSMutableSet *xLabels = [NSMutableSet setWithCapacity:dateCount];
NSMutableSet *xLocations = [NSMutableSet setWithCapacity:dateCount];
NSInteger i = 0;
for (NSString *d in self.arrayData)
{
    NSLog(@":%@",d);

    CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:d  textStyle:axisSet.xAxis.labelTextStyle];
    //        [label setRotation:45.0];
    CGFloat location = i++;
    label.tickLocation = CPTDecimalFromCGFloat(location);
    label.offset = axisSet.xAxis.majorTickLength;
    //label.rotation = M_PI/4;
    if (label) {
        [xLabels addObject:label];
        [xLocations addObject:[NSNumber numberWithFloat:location]];
    }
}

x.axisLabels=xLabels;

CPTMutableLineStyle *gridLineStyle = [CPTMutableLineStyle lineStyle];
gridLineStyle.dashPattern=[NSArray arrayWithObjects:[NSDecimalNumber numberWithInt:1],[NSDecimalNumber numberWithInt:2],nil];    


CPTXYAxis *y = axisSet.yAxis;

NSMutableArray  *ylabelTick=[[NSMutableArray alloc] initWithObjects:@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8", nil];

y.labelingPolicy = CPTAxisLabelingPolicyNone;
y.majorIntervalLength = CPTDecimalFromInteger(0.5);
y.minorTicksPerInterval = 0;
y.majorTickLineStyle = lineStyle;
y.minorTickLineStyle = lineStyle1;
y.axisLineStyle = lineStyle2;
y.minorTickLength = 3.0f;
y.majorTickLength = 5.0f;
y.labelOffset=10.0f;    
y.orthogonalCoordinateDecimal=CPTDecimalFromDouble(0.0);
y.majorTickLocations=[NSSet setWithArray:ylabelTick];
y.visibleRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0) length:CPTDecimalFromFloat([arrayDataY count])];
y.gridLinesRange=[CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat( 0 ) length:CPTDecimalFromFloat([arrayData count] )];
y.majorGridLineStyle=gridLineStyle;
CGFloat dateCounty = [self.arrayData count];
NSMutableSet *yLabels = [NSMutableSet setWithCapacity:dateCounty];
NSMutableSet *yLocations = [NSMutableSet setWithCapacity:dateCounty];
NSInteger j = 0;
for (NSString *d in self.arrayDataY)
{
    CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:d  textStyle:axisSet.yAxis.labelTextStyle];
    //        [label setRotation:45.0];
    CGFloat location = j++;
    label.tickLocation = CPTDecimalFromCGFloat(location);
    label.offset = axisSet.yAxis.majorTickLength;
    if (j<7) {
        [label setAlignment:CPTAlignmentBottom];
    }

    //label.rotation = M_PI/4;
    if (label) {
        [yLabels addObject:label];
        [yLocations addObject:[NSNumber numberWithFloat:location]];
    }
}

y.axisLabels=yLabels;

CPTXYPlotSpace *plotSpace2 =[[CPTXYPlotSpace alloc] init];
plotSpace2.xRange = plotSpace.xRange;

plotSpace2.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0) length:CPTDecimalFromFloat([arrayDataY count])];

[plotSpace2 setAllowsUserInteraction:YES];
[graph addPlotSpace:plotSpace2];


CPTXYAxis *y2 = [[CPTXYAxis alloc] init];
y2.plotSpace    =plotSpace2;
y2.labelingPolicy = CPTAxisLabelingPolicyNone;
y2.orthogonalCoordinateDecimal = CPTDecimalFromFloat([arrayData count]);
y2.majorTickLineStyle=lineStyle;
y2.minorTickLineStyle=lineStyle1;
y2.axisLineStyle = lineStyle2;
y2.minorTicksPerInterval = 2;
y2.majorIntervalLength   = CPTDecimalFromInteger(1);
y2.minorTickLength=5;
y2.coordinate          =CPTCoordinateY;        
y2.labelOffset                 = -30.0f;
y2.majorTickLocations=[NSSet setWithArray:ylabelTick];
y2.visibleRange                = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0) length:CPTDecimalFromFloat([arrayDataY count])];
y2.axisLabels=yLabels;

graph.axisSet.axes = [NSArray arrayWithObjects:x, y, y2, nil];

}

Please help me to add multiple y axis with custom label. also i want same x axis values in top of graph also (i.e. have two x axes, one at the top and one at the bottom).

enter image description here In above image y2 axis label not showing. How to set y2 axis label with custom label


Solution

  • Your approach is correct. All you need now is to create more axes and add them to the axis set. In my example I created an indicator line that moves with the mouse pointer when the mouse is over the graph. You can easily adjust that for fixed x and y axes (see the .coordinate member to determine what type of axis it should be).

    // The second y axis is used as the current location identifier.
    mainIndicatorLine = [[CPTXYAxis alloc] init];
    mainIndicatorLine.hidden = YES;
    mainIndicatorLine.coordinate = CPTCoordinateY;
    mainIndicatorLine.plotSpace = plotSpace;
    mainIndicatorLine.axisConstraints = [CPTConstraints constraintWithLowerOffset: 0];
    mainIndicatorLine.labelingPolicy = CPTAxisLabelingPolicyNone;
    mainIndicatorLine.separateLayers = YES;
    mainIndicatorLine.preferredNumberOfMajorTicks = 6;
    mainIndicatorLine.minorTicksPerInterval = 0;
    
    CPTMutableLineStyle *lineStyle = [CPTMutableLineStyle lineStyle];
    lineStyle.lineWidth = 1;
    lineStyle.lineColor = [CPTColor colorWithGenericGray: 64 / 255.0];
    lineStyle.lineCap = kCGLineCapRound;
    lineStyle.dashPattern = @[@10.0f, @5.0f];
    mainIndicatorLine.axisLineStyle = lineStyle;
    mainIndicatorLine.majorTickLineStyle = nil;
    
    // Add the mainIndicatorLine to the axis set.
    // It is essential to first assign the axes to be used in the arrayWithObject call
    // to local variables or all kind of weird things start showing up later (mostly with invalid coordinates).
    CPTXYAxisSet *axisSet = (id)mainGraph.axisSet;
    CPTXYAxis    *x = axisSet.xAxis;
    CPTXYAxis    *y = axisSet.yAxis;
    axisSet.axes = @[x, y, mainIndicatorLine];