水平条形图上的Core Plot ScatterPlot

时间:2015-09-04 06:53:02

标签: ios objective-c core-plot

我尝试使用条形图上的ScatterPlot显示一条线,该线是水平的。它适用于垂直条形图,但不适用于水平条形图。

这是源代码:

-(id)init
{
    if ( (self = [super init]) ) {
        self.section = kBarPlots;
        self.isOneBarPlot = TRUE;
    }

    return self;
}

-(void)generateData
{
    [[BPDatabaseController sharedController] dataForTopFiveObservationPeriodIncidents:^(NSArray *resultArray) {

        self.plotData = resultArray;
        FilterManager *fm = [FilterManager sharedInstance];

        self.isOneBarPlot = fm.filterPendingIncidents; //is responsible for showing the legend correctly
        [self renderInLayer:self.defaultLayerHostingView withTheme:self.theme animated:YES];
        [super generateData];

    }];
}

-(void)renderInLayer:(CPTGraphHostingView *)layerHostingView withTheme:(CPTTheme *)theme animated:(BOOL)animated
{
    CGRect bounds = layerHostingView.bounds;

    CPTGraph *graph = [[CPTXYGraph alloc] initWithFrame:bounds];
    [self addGraph:graph toHostingView:layerHostingView];
    [self applyTheme:theme toGraph:graph withDefault:nil];

    [self setTitleDefaultsForGraph:graph withBounds:bounds];
    [self setPaddingDefaultsForGraph:graph withBounds:bounds];



    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
        graph.paddingLeft = 0.0f;
    }else{
        graph.paddingLeft = 65.0f;
    }

    graph.paddingRight = 0.0f;

    NSNumberFormatter *format = [[NSNumberFormatter alloc] init];
    [format setNumberStyle:NSNumberFormatterNoStyle];

    // Create bar plot
    CPTBarPlot *barPlot = [[CPTBarPlot alloc] init];
    barPlot.lineStyle         = [[CPTTheme themeNamed:kCPTDarkBlueTheme] axisLineStyle:kBarLineStyle];
    barPlot.barWidth          = CPTDecimalFromFloat(0.60f); // bar is 75% of the available space
    barPlot.barCornerRadius   = 0.0;
    barPlot.barsAreHorizontal = YES;
    barPlot.dataSource        = self;
    barPlot.identifier        = kBarPlotPending;
    barPlot.delegate          = self;
    barPlot.fill                = [[CPTTheme themeNamed:kCPTDarkBlueTheme] barFillForBarPlotOfType:kHorizontalRed];
    barPlot.labelTextStyle      = [[CPTTheme themeNamed:kCPTDarkBlueTheme] barTextStyle];
    barPlot.labelFormatter  = format;
    barPlot.labelOffset =  1.0;
    barPlot.anchorPoint = CGPointMake(0.0, 0.0);
    [barPlot addAnimation:[self plotAnimationWithKeyPath:@"transform.scale.x"] forKey:@"someKey"];

    if(!self.isOneBarPlot){
        [graph addPlot:barPlot];
    }

    // Create bar plot
    CPTBarPlot *barPlot2 = [[CPTBarPlot alloc] init];
    barPlot2.lineStyle         = [[CPTTheme themeNamed:kCPTDarkBlueTheme] axisLineStyle:kBarLineStyle];;
    barPlot2.barWidth          = CPTDecimalFromFloat(0.60f); // bar is 75% of the available space
    barPlot2.barCornerRadius   = 0.0;
    barPlot2.barsAreHorizontal = YES;
    barPlot2.dataSource        = self;
    barPlot2.identifier        = kBarPlotOfficial;
    barPlot2.delegate          = self;
    barPlot2.labelFormatter  = format;
    barPlot2.fill               = [[CPTTheme themeNamed:kCPTDarkBlueTheme] barFillForBarPlotOfType:kHorizontalBlue];
    barPlot2.anchorPoint = CGPointMake(0.0, 0.0);
    barPlot2.labelTextStyle     = [[CPTTheme themeNamed:kCPTDarkBlueTheme] barTextStyle];
    if(!self.isOneBarPlot){
        barPlot2.labelOffset =  -1.0;
    }
    [graph addPlot:barPlot2];



    [barPlot2 addAnimation:[self plotAnimationWithKeyPath:@"transform.scale.x"] forKey:@"someKey"];

    // make the bars thinner if only one data set is available
    if ([self.plotData count] == 1) {
        barPlot.barWidthScale = kBarWithScaleOneItem;
        barPlot2.barWidthScale = kBarWithScaleOneItem;
    }

    if ([self.plotData count] > 0) {

        // Plot space
        CPTMutablePlotRange *barRange = [[barPlot plotRangeEnclosingBars] mutableCopy];
        [barRange expandRangeByFactor:CPTDecimalFromDouble(1.05)];


        CPTXYPlotSpace *barPlotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
        barPlotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0f) length:CPTDecimalFromFloat([self calculateDatasourcePeak])];
        barPlotSpace.yRange = barRange;

        CPTScatterPlot *targetLinePlot = [[CPTScatterPlot alloc] init];
        targetLinePlot.identifier = kBarPlotTarget;
        targetLinePlot.title = NSLocalizedString(kBarPlotTarget, nil);

        CPTMutableLineStyle *barLineStyleTarget = [[CPTMutableLineStyle alloc] init];
        barLineStyleTarget.lineWidth = 2.0;
        barLineStyleTarget.lineColor = [CPTColor grayColor];

        targetLinePlot.dataLineStyle = barLineStyleTarget;
        targetLinePlot.dataSource = self;
        [graph addPlot:targetLinePlot toPlotSpace:barPlotSpace];



        [self configureAxis:graph];

        [self createDarkBackgroundPlot:graph isHorizontal:TRUE];

    }else{

        self.emtyPlot.alpha = 1.0;

        // Create axes
        CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
        CPTXYAxis *y          = axisSet.yAxis;
        {
            y.majorIntervalLength         = CPTDecimalFromInteger(0);
            y.axisLineStyle               = nil;
            y.labelingPolicy              = CPTAxisLabelingPolicyNone;
            y.labelTextStyle              = nil;
            y.majorTickLineStyle    = nil;
            y.minorTickLineStyle = nil;
            y.axisConstraints             = [CPTConstraints constraintWithLowerOffset:7.0];

        }

        CPTXYAxis *x = axisSet.xAxis;
        {
            x.majorIntervalLength         = CPTDecimalFromInteger(0);
            x.axisConstraints             = [CPTConstraints constraintWithLowerOffset:8.0];
            x.axisLineStyle               = nil;
            x.labelingPolicy              = CPTAxisLabelingPolicyAutomatic;
            x.majorTickLineStyle    = nil;
            x.minorTickLineStyle = nil;
            x.labelTextStyle = nil;

        }
    }
}

-(void)configureAxis:(CPTGraph *)graph{

    [super configureAxis:graph];

    NSNumberFormatter *format = [[NSNumberFormatter alloc] init];
    [format setNumberStyle:NSNumberFormatterNoStyle];

    //legend
    CPTLegend *theLegend = [CPTLegend legendWithGraph:graph];
    theLegend.borderLineStyle = [[CPTTheme themeNamed:kCPTDarkBlueTheme] axisLineStyle:kBarLineStyle];
    theLegend.cornerRadius    = 0.0;
    theLegend.swatchSize      = CGSizeMake(16.0, 16.0);
    theLegend.textStyle     = [[CPTTheme themeNamed:kCPTDarkBlueTheme] barTextStyle];
    theLegend.numberOfRows  = 1;
    graph.legend             = theLegend;
    graph.legendAnchor       = CPTRectAnchorBottom;
    graph.legendDisplacement = CGPointMake(0.0, 0.0);

    // Create axes
    CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
    CPTXYAxis *y          = axisSet.yAxis;
    {
        y.majorIntervalLength         = CPTDecimalFromInteger(1);
        y.axisLineStyle               = [[CPTTheme themeNamed:kCPTDarkBlueTheme] axisLineStyle:kYAxisLineStyle];
        y.labelingPolicy              = CPTAxisLabelingPolicyNone;
        y.orthogonalCoordinateDecimal = CPTDecimalFromInteger(1);
        y.labelTextStyle = [[CPTTheme themeNamed:kCPTDarkBlueTheme] barTextStyle];
        y.axisConstraints             = [CPTConstraints constraintWithLowerOffset:5.0];
    }

    NSMutableSet *yAxisLegend = [NSMutableSet set];

    for (int i = 0; i < self.plotData.count; i++) {
        CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithText:[self addLineBreakToString:(NSString*)[[self.plotData objectAtIndex:i] objectForKey:kResultLabel] ]textStyle:[[CPTTheme themeNamed:kCPTDarkBlueTheme] barTextStyle]];
        label.tickLocation = CPTDecimalFromInteger(i);

        [yAxisLegend addObject:label];
    }
    y.axisLabels = yAxisLegend;


    CPTXYAxis *x = axisSet.xAxis;
    {
        x.majorIntervalLength         = CPTDecimalFromInteger(1);
        x.axisConstraints             = [CPTConstraints constraintWithLowerOffset:8.0];
        x.axisLineStyle               = [[CPTTheme themeNamed:kCPTDarkBlueTheme] axisLineStyle:kXAxisLineStyle];
        x.labelingPolicy              = CPTAxisLabelingPolicyAutomatic;
        x.majorTickLineStyle = nil;
        x.minorTickLineStyle = nil;
        //x.labelFormatter = format;
        x.orthogonalCoordinateDecimal = CPTDecimalFromInteger(-1);
        x.labelTextStyle = [[CPTTheme themeNamed:kCPTDarkBlueTheme] barTextStyle];
        x.labelOffset = 5.0f;

    }
}

#pragma mark -
#pragma mark Plot Data Source Methods

-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{

    return self.plotData.count;
}

-(NSArray *)numbersForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndexRange:(NSRange)indexRange
{
    NSArray *nums = [super numbersForPlot:plot field:fieldEnum recordIndexRange:indexRange];

    if (!nums) {
        switch ( fieldEnum ) {
            case CPTBarPlotFieldBarLocation:
                nums = [NSMutableArray arrayWithCapacity:indexRange.length];
                for ( NSUInteger i = indexRange.location; i < NSMaxRange(indexRange); i++ ) {
                    [(NSMutableArray *)nums addObject : @(i)];
                }
                break;

            case CPTBarPlotFieldBarTip: {

                if ([plot.identifier isEqual:kBarPlotTarget]) {

                    nums = [NSMutableArray arrayWithCapacity:indexRange.length];
                    for ( NSUInteger i = indexRange.location; i < NSMaxRange(indexRange); i++ ) {
                        [(NSMutableArray *)nums addObject:@(100)];
                    }

                }else{

                NSString *dataKey = nil;
                if ([plot.identifier isEqual:kBarPlotOfficial]) {
                    dataKey = kResultOfficial;
                }
                else {
                    dataKey = kResultSum;
                }

                nums = [NSMutableArray arrayWithCapacity:indexRange.length];
                for ( NSUInteger i = indexRange.location; i < NSMaxRange(indexRange); i++ ) {

                    NSNumber *number = [[self.plotData objectAtIndex:i] objectForKey:dataKey];
                    [(NSMutableArray *)nums addObject : number];
                }
                }
                break;
            }

            default:
                break;
        }
    }
    return nums;
}

-(CPTLayer *)dataLabelForPlot:(CPTPlot *)plot recordIndex:(NSUInteger)idx
{
    CPTTextLayer *textLayer = (id)[NSNull null];;
    NSNumber *number = nil;

    if ([plot.identifier isEqual:kBarPlotPending]) {
        number = [[self.plotData objectAtIndex:idx] objectForKey:kResultSum];

    }
    else if ([plot.identifier isEqual:kBarPlotOfficial]) {

        NSNumber *officialNumber = [[self.plotData objectAtIndex:idx] objectForKey:kResultOfficial];
        NSNumber *pendingNumber = [[self.plotData objectAtIndex:idx] objectForKey:kResultSum];

        CGFloat maxNumber = [self calculateDatasourcePeak];

        // 1.) if the max peak it to high and the current value to low the
        //     official is not shown correclty (not enough space) => do not show it
        // 2.) do not show the official if its the same number as pending
        if (!(maxNumber > 100 && [officialNumber intValue] < 50) && ([officialNumber intValue] != [pendingNumber intValue])) {
            number = officialNumber;
        }
    }

    if ([number intValue] > 0) {
        textLayer = [[CPTTextLayer alloc] initWithText:[number stringValue] style:[[CPTTheme themeNamed:kCPTDarkBlueTheme] barTextStyle]];
    }

    return textLayer;
}

#pragma mark - CPTBarPlot delegate methods

-(void)plot:(CPTPlot *)plot dataLabelWasSelectedAtRecordIndex:(NSUInteger)index
{
    NSLog(@"Data label for '%@' was selected at index %d.", plot.identifier, (int)index);
}

底部的图例确实显示应该有一条目标线,但不会显示任何人

1 个答案:

答案 0 :(得分:0)

不同的绘图类型使用不同的数据源字段枚举。条形图将使用CPTBarPlotFieldBarLocationCPTBarPlotFieldBarTip。像目标线图一样的散点图将使用CPTScatterPlotFieldXCPTScatterPlotFieldY。确保数据源正在检查每个图的右侧字段枚举值。