2015-09-04 138 views
1

我試圖在水平條形圖上使用散點圖來顯示一條線。它適用於垂直條形圖,但不適用於水平條形圖。水平條形圖上的核心散點圖散點圖

這是源代碼:

-(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); 
} 

在底部的圖例它只表示應該有一個目標行,但沒有一個被顯示

+0

你可以發佈其餘的數據源方法嗎?確保' - numberForPlot:field:recordIndex:'或你使用的任何數據方法檢查正確的字段。條形圖將詢問「CPTBarPlotFieldBarLocation」和「CPTBarPlotFieldBarTip」字段的數據源。 –

+0

我試圖實現它。它仍然不會顯示一條線。我已經編輯了上面的新代碼 – user2529173

回答

0

不同情節類型使用不同的數據源字段枚舉。條形圖將使用CPTBarPlotFieldBarLocationCPTBarPlotFieldBarTip。類似目標線圖的散點圖將使用CPTScatterPlotFieldXCPTScatterPlotFieldY。確保數據源正在檢查每個圖的右側字段枚舉值。