核心图:最初在外部的y轴标签,但随后在内部图中

时间:2012-02-01 17:47:25

标签: positioning core-plot axis-labels

我正在使用Core-Plot 0.9并且有一个看似奇怪的问题。我有一个带有Y轴标签的X-Y图。最初显示绘图时,标签正确定位在轴本身左侧的刻度线(实际偏移1.0)上,这是正确的。

然后,我选择要使用UIPickerView显示的新数据集来设置x轴起点并重新生成绘图。在该图和随后的绘图重新生成中,y轴标签显示在绘图内(轴的右侧)而不是刻度标记(实际上向上移动了一点。

我已经创建了我认为在图的左侧足够的空间来包含y轴标签。特别是,我的代码如下:

graph.paddingLeft = 0.0;
graph.plotAreaFrame.paddingLeft = 25.0;

y.labelOffset = 1.0f;
y.labelAlignment = CPTAlignmentLeft;

这是初始加载时y轴标签的正确表示。

http://www.msyapps.com/gifs/Correct.png

在滚动左侧的选择器视图并重新生成绘图后,以下是y轴标签的错误表示。

http://www.msyapps.com/gifs/Incorrect.png

2 个答案:

答案 0 :(得分:1)

您要更改tickDirection属性吗?这就是控制标签所在的一面。

答案 1 :(得分:1)

我有一个可行的解决方案,但它违反了通常建议的显示y轴的操作。下面的代码片段中的注释表示我认为我偏离惯例的地方以及我认为我已经添加了一个独特的解决方案,用于在随后的重绘图上修复y轴。

#pragma mark - Choose returns to chart
- (IBAction)returnsToChart:(int)startPt andInteger:(int)endPt; { 
    contentArray1 = [[NSMutableArray alloc] initWithObjects:nil];
    dataContent = [[NSMutableArray alloc] initWithObjects:nil];
    int xPosition = 0;
    for (int i=startPt; i<endPt+1; ++i) {
        [dataContent addObject:[returnsAll objectAtIndex:i]];
        id x = [NSNumber numberWithFloat:xPosition];
        id y = [NSNumber numberWithFloat:[[returnsAll objectAtIndex:i] floatValue]];
        if ([[returnsAll objectAtIndex:i] isEqualToString:@""]) {
            [contentArray1 addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:x, @"x", @"", @"y", nil]];
        }
        else {
            [contentArray1 addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:x, @"x", y, @"y", nil]]; }
        xPosition = xPosition + 1;
    }

    dataForPlot = contentArray1;

    quarterlyReturnView.frame = CGRectMake(0.0f, 8.0f, 320.0f, 240.0f);    

    graph = [[CPTXYGraph alloc] initWithFrame:CGRectZero];    
    quarterlyReturnView.hostedGraph = graph;

    //paddingLeft leaves room for y-axis labels
    //paddingBottom must be set at zero otherwise and the space that must be added in order for the bottom-most label text to show will be handled by extending the length of the y-axis downward by a little bit
    graph.paddingLeft = 8.0;
    graph.paddingTop = 5.0;
    graph.paddingRight = 5.0;
    graph.paddingBottom = 0.0;

    //convention says that paddingLeft should be some number greater than zero
    //convention says that paddingBottom should be some number greater than zero, but if greater than zero, then each subsequent redrawing of plot results in a label shift upwards by the non-zero amount
    graph.plotAreaFrame.paddingLeft = 0.0;
    graph.plotAreaFrame.paddingTop = 5.0;
    graph.plotAreaFrame.paddingRight = 5.0;
    graph.plotAreaFrame.paddingBottom = 0.0;

    // Setup plot space
    CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;

    //this is where the magic happens...
    //I tweaked the percentage adjustments for the location as a function of the number of data points along the x-axis that had to be plotted
    //I settled on 8% plus and minus to provide room for the y-axis labels
    //this percentage is expressed as -0.08*(datacontent.count-1.0) and 1.08*(datacontent.count-1.0)
    //in other words, I put 8% on the left-hand side of the x-axis and made the whole x-axis 108% of the number of data points

    plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(-0.08 * (dataContent.count-1.0)) length:CPTDecimalFromFloat(1.08 * (dataContent.count-1.0))];

    //Text styles
    CPTMutableTextStyle *axisTitleTextStyle = [CPTTextStyle textStyle];
    axisTitleTextStyle.fontName = @"Helvetica";
    axisTitleTextStyle.fontSize = 9.0;

    //Grid styles
    CPTMutableLineStyle *majorGridLineStyle = [CPTLineStyle lineStyle];
    majorGridLineStyle.lineWidth = 0.5f;

    //Axis styles
    CPTMutableLineStyle *axisLineStyle = [CPTLineStyle lineStyle];
    axisLineStyle.lineColor = [CPTColor blueColor];
    axisLineStyle.lineWidth = 1.0f;

    float maxNum = -100.0;
    float minNum = 100.0;
    float testMaxNum = 0.0;
    float testMinNum = 0.0;
    for (int i=0; i<[dataContent count]; ++i) {
        if ([[dataContent objectAtIndex:i] isEqualToString:@""]) { }
        else {
            testMaxNum = [[dataContent objectAtIndex:i] floatValue];
            if (maxNum < testMaxNum) { maxNum = testMaxNum; }
            testMinNum = [[dataContent objectAtIndex:i] floatValue];
            if (minNum > testMinNum) { minNum = testMinNum; } }
    }
    int maxInt = (maxNum + 1.0) / 1.0;
    float yMax = 1.0 * maxInt;
    int minInt = (minNum - 1.0) / 1.0;
    float yMin = 1.0 * minInt;

    //here is where the y-axis is stretched a bit to allow the labels to show unclipped
    plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(yMin-0.2) length:CPTDecimalFromFloat(yMax-yMin+0.2)];

    // Axes (x is horizontal; y is vertical)
    CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
    CPTXYAxis *x = axisSet.xAxis;
    x.axisLineStyle = axisLineStyle;
    x.labelOffset = 1.0f;
    x.labelTextStyle = nil;
    x.majorTickLength = 5.0f;
    x.majorIntervalLength = CPTDecimalFromString(@"16");
    x.orthogonalCoordinateDecimal = CPTDecimalFromString(@"0");
    x.minorTicksPerInterval = 0;
    x.minorTickLength = 0.0f;
    x.tickDirection =CPTSignNone;
    x.visibleRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0) length:CPTDecimalFromFloat(dataContent.count-1.0)];

    CPTXYAxis *y = axisSet.yAxis;
    y.axisLineStyle = axisLineStyle;
    NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
    [formatter setMaximumFractionDigits:0];
    y.labelFormatter = formatter;
    y.labelOffset = 2.0f;
    y.labelAlignment = CPTAlignmentLeft;
    y.labelTextStyle = axisTitleTextStyle;
    y.tickDirection = CPTSignNegative;    
    y.majorTickLength = 3.0f;    
    y.majorIntervalLength = CPTDecimalFromString(@"2");
    y.majorGridLineStyle = majorGridLineStyle;
    //y.gridLinesRange is needed because the x-axis has been stretched 8% as described above
    y.gridLinesRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromInt(0) length:CPTDecimalFromInt(dataContent.count-1)];
    y.minorTicksPerInterval = 1;
    y.minorTickLength = 2.0f;
    y.orthogonalCoordinateDecimal = CPTDecimalFromString(@"0");

    // Create plot area
    CPTScatterPlot *boundLinePlot = [[CPTScatterPlot alloc] init];
    CPTMutableLineStyle *lineStyle = [CPTMutableLineStyle lineStyle];
    lineStyle.miterLimit = 1.0f;
    lineStyle.lineWidth = 2.0f;
    lineStyle.lineColor = [CPTColor blueColor];
    boundLinePlot.dataLineStyle = lineStyle;
    boundLinePlot.dataSource = self;
    [graph addPlot:boundLinePlot];
    [boundLinePlot reloadData];
}