如何在核心图条形图中添加椭圆

时间:2016-01-27 19:21:49

标签: ios objective-c core-plot

条形图上带有椭圆的图像是所需的结果。我继承了创建显示人血压的条形图的代码。我的任务是在条形图的顶部绘制一个椭圆来显示人的心率。所以我使用相同的x轴,但我相信我需要添加另一个Y轴。这是代码。我添加了第二个plotspace(plotspace2)和另一个y轴(rightY)。任何帮助都将受到赞赏

    @interface BPGraphView()

    @property (nonatomic) CPTXYGraph* graph;
    @property (nonatomic) CPTBarPlot* plot;
    @property (nonatomic) CPTScatterPlot* plotGoal;
    @property (nonatomic) CPTBarPlot* plotHeartRate;

    @end

    @implementation BPGraphView


    - (void)layoutSubviews {
      [super layoutSubviews];
      [self setupGraph];
      [self setupAxes];
      [self setupGoalAnnotation];
      [self.graph reloadData];

    }

      - (void)setupGraph {
         if (!self.graph) {

         self.graph = [[CPTXYGraph alloc] init];
         self.hostedGraph = self.graph;
         self.graph.paddingTop    = 0;
         self.graph.paddingBottom = 0;
         self.graph.paddingLeft   = 0;
         self.graph.paddingRight  = 0;

         // We need to rasterize the graph, otherwise performance is poor    when scrolling
         self.layer.shouldRasterize = YES;

         UIParam* uiParam = [UIParam sharedUIParam];

         // a single dashed line showing the daily goal
         self.plotGoal = [[CPTScatterPlot alloc] init];
         [self.graph addPlot:self.plotGoal];
         self.plotGoal.dataSource = self;
         CPTMutableLineStyle *lineStyleDash = [[CPTMutableLineStyle alloc] init];
         lineStyleDash.lineWidth = 2;
         lineStyleDash.lineColor = [CPTColor   colorWithCGColor:uiParam.colorGoalLine.CGColor];
    //        lineStyleDash.dashPattern = @[ @7, @3 ];
         lineStyleDash.lineJoin = kCGLineJoinRound;
         self.plotGoal.dataLineStyle = lineStyleDash;

         self.plot = [[CPTBarPlot alloc] init];
         [self.graph addPlot:self.plot];
         self.plot.dataSource = self;

         self.plot.fill = [[CPTFill alloc] initWithColor:[CPTColor colorWithCGColor:[[UIColor colorWithHexString:kBarColorString] CGColor]]];
         self.plot.lineStyle = nil;

         self.graph.defaultPlotSpace.allowsUserInteraction = NO;
  }
         self.graph.frame = self.bounds;
         self.plot.frame = CGRectMake(0.0, 0.0, self.bounds.size.width,   self.bounds.size.height - 10.0);
}

         - (void)setupAxes {

         // Plot space ranges

         //int dailyGoal = 0;//[self.data.stepsSummary.dailyStepsGoal.steps intValue];
         float maxY = 190.0;

         for (YMBPSeries* bpEntry in self.data.bpSeries) {

         if (bpEntry.systolic > maxY)
       {
         maxY = bpEntry.systolic;
       }
    }

         NSLog(@"MaxY = %f", maxY);  // TODO: temp debug


        CPTXYPlotSpace* plotSpace =   (CPTXYPlotSpace*)self.graph.defaultPlotSpace;
        if (self.data.dayInterval == YMDayInterval7Day) {
        plotSpace.xRange = [CPTPlotRange   plotRangeWithLocation:CPTDecimalFromFloat(-2)  length:CPTDecimalFromFloat(9)]; // 7 values + a little extra before for y axis labels
        }
        else {
        plotSpace.xRange = [CPTPlotRange   plotRangeWithLocation:CPTDecimalFromFloat(-4)  length:CPTDecimalFromFloat(18)]; // 14 values + a little extra before for y axis labels
        }

        plotSpace.yRange = [CPTPlotRange  plotRangeWithLocation:CPTDecimalFromFloat(-maxY * .10)  length:CPTDecimalFromFloat(maxY * 1.4)]; // add some space before (for  labels) and after

       self.plot.barWidth = CPTDecimalFromFloat(0.25);

      //Heartrate Plot
      CPTXYPlotSpace* plotSpace2 = [[CPTXYPlotSpace alloc] init];
      plotSpace2.xRange = plotSpace.xRange;
      plotSpace2.yRange = [CPTPlotRange   plotRangeWithLocation:CPTDecimalFromFloat(0.0)  length:CPTDecimalFromFloat(400.0)];
      [_graph addPlotSpace:plotSpace2];


      // Axes
      CPTXYAxisSet *axisSet = (CPTXYAxisSet *)self.graph.axisSet;

      CPTXYAxis *xAxis = axisSet.xAxis;
      xAxis.majorIntervalLength = CPTDecimalFromInt(1);
      xAxis.orthogonalCoordinateDecimal = CPTDecimalFromInt(0);
      xAxis.majorGridLineStyle = nil;
      xAxis.minorGridLineStyle = nil;
      xAxis.majorTickLineStyle = nil;
      xAxis.minorTickLineStyle = nil;
      xAxis.axisLineStyle = nil;
      xAxis.labelingPolicy = CPTAxisLabelingPolicyNone;
      CPTMutableTextStyle* textStyle = [CPTMutableTextStyle textStyle];
      textStyle.fontName = kLabelFontName;
      textStyle.fontSize = FONT_SIZE_AXIS_LABEL;
      textStyle.color = [CPTColor blackColor];
      xAxis.labelTextStyle = textStyle;
      xAxis.axisLabels = [GraphUtil xAxisLabels:self.data.dayInterval  start:self.data.startDate style:xAxis.labelTextStyle leftText:nil];

      CPTXYAxis *yAxis  = axisSet.yAxis;
      yAxis.majorIntervalLength = CPTDecimalFromInt(10);
      yAxis.minorTicksPerInterval = 0;
      yAxis.orthogonalCoordinateDecimal = CPTDecimalFromInteger(0);

      //Setup Heart Rate YAxis
      CPTXYAxis *rightY = [(CPTXYAxis *)[CPTXYAxis alloc]  initWithFrame:CGRectZero];
      rightY.coordinate = CPTCoordinateY;
      rightY.plotSpace = plotSpace2;
      rightY.orthogonalCoordinateDecimal = CPTDecimalFromInteger(0);

      CPTMutableLineStyle *majorGridLineStyle = [CPTMutableLineStyle lineStyle];
      majorGridLineStyle.lineWidth = 0.20;
      majorGridLineStyle.lineColor = [CPTColor lightGrayColor];

      yAxis.majorGridLineStyle = majorGridLineStyle;
      yAxis.minorGridLineStyle = nil;
      yAxis.majorTickLineStyle = nil;
      yAxis.minorTickLineStyle = nil;
      yAxis.axisLineStyle = nil;
      yAxis.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
      yAxis.preferredNumberOfMajorTicks = 8;
      NSNumberFormatter *labelFormatter = [[NSNumberFormatter alloc] init];
      labelFormatter.numberStyle = NSNumberFormatterDecimalStyle;
      yAxis.labelFormatter = labelFormatter;
      yAxis.labelOffset = 0;
     //  yAxis.titleOffset = 54;
      yAxis.title = @"mmHg";

      rightY.majorGridLineStyle = majorGridLineStyle;
      rightY.minorGridLineStyle = nil;
      rightY.majorTickLineStyle = nil;
      rightY.minorTickLineStyle = nil;
      rightY.axisLineStyle = nil;
      rightY.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
      rightY.preferredNumberOfMajorTicks = 8;
      NSNumberFormatter *labelFormatter2 = [[NSNumberFormatter alloc] init];
      labelFormatter.numberStyle = NSNumberFormatterDecimalStyle;
      rightY.labelFormatter = labelFormatter2;
      rightY.labelOffset = 0;
      rightY.title = @"bpm";

      NSMutableArray* exclusionRanges = [NSMutableArray array];
      //  // do not label 0
      //  [exclusionRanges addObject:[CPTPlotRange   plotRangeWithLocation:CPTDecimalFromFloat(1)  length:CPTDecimalFromFloat(-99999)]];
     //  
     //  // do not label the daily goal, or nearby, because it gets a custom annotation
     //  if (dailyGoal > 0) {
    //    [exclusionRanges addObject:[CPTPlotRange   plotRangeWithLocation:CPTDecimalFromFloat(dailyGoal - maxY*0.05) length:CPTDecimalFromFloat(maxY*.1)]];
     //  }

     // do not label max number, because sometimes the label is cut off at the top, which looks bad
    [exclusionRanges addObject:[CPTPlotRange  plotRangeWithLocation:CPTDecimalFromFloat(maxY+1) length:CPTDecimalFromFloat(99999)]];

    yAxis.labelExclusionRanges = exclusionRanges;

    // yAxis.title = @"mmHg";
   }

    // add an annotation to label the daily goal.
    // It is positioned at the left of the graph, just to the right of   the axis, above 12AM.
    // At this position we are mostly safe from interference from the daily steps graph.
    // Also we do not put it over the Y labels, since those are automatically generated.
    - (void)setupGoalAnnotation {

     [self.graph.plotAreaFrame.plotArea removeAllAnnotations];

     NSNumber* dailyGoal = 0;
     if ([dailyGoal intValue] > 0) {

     CPTXYAxisSet *axisSet = (CPTXYAxisSet *)self.graph.axisSet;
     CPTXYAxis *yAxis = axisSet.yAxis;


     // custom labels for threshholds
     CPTMutableTextStyle* textStyleThreshhold = [yAxis.labelTextStyle mutableCopy];
     textStyleThreshhold.fontName = kLabelFontName;
     textStyleThreshhold.textAlignment = CPTTextAlignmentCenter;
     textStyleThreshhold.fontSize = textStyleThreshhold.fontSize - 4.0;

     UIParam* uiParam = [UIParam sharedUIParam];

     CPTBorderedLayer* layerAnnotation = [GraphUtil borderedTextLayer:  [dailyGoal description] style:textStyleThreshhold margin:CGSizeMake(4, 4)];
     layerAnnotation.fill = [CPTFill fillWithColor:[CPTColor whiteColor]];
     layerAnnotation.borderColor = uiParam.colorGoalLine.CGColor;
     layerAnnotation.borderWidth = 2.0;

     CGFloat x = 0.0;

     switch (self.data.dayInterval) {
      case YMDayInterval1Day:
        x = 22.9;
        break;

      case YMDayInterval7Day:
        x = 6.60;
        break;

      case YMDayInterval14Day:
        x = 13.2;
        break;

      default:
        break;
    }

     NSArray* anchorPoint = @[@(x), dailyGoal ];
     CPTPlotSpaceAnnotation* annotation = [[CPTPlotSpaceAnnotation alloc] initWithPlotSpace:self.graph.defaultPlotSpace anchorPlotPoint:anchorPoint];
    annotation.contentLayer = layerAnnotation;

      [self.graph.plotAreaFrame.plotArea addAnnotation:annotation];
    }
  }


   #pragma mark - CPTPlotDataSource delegate

     - (NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot {
        if (plot == self.plotGoal) {
        return 2;
    }
     else {
       if (self.data.dayInterval == YMDayInterval7Day)
        return 7;
        return 14;
    }
 }

     - (NSNumber *)numberForPlot:(CPTPlot *)plot field:   (NSUInteger)fieldEnum recordIndex:(NSUInteger)idx {

     if (plot == self.plotGoal) {
        if (fieldEnum == CPTScatterPlotFieldX) {
          if (idx == 0)
           return @(-1);
        else
           return @(9999);
      }
       else if (fieldEnum == CPTScatterPlotFieldY) {
        return 0;//self.data.stepsSummary.dailyStepsGoal.steps;
      }
    }
     else {
        if (fieldEnum == CPTBarPlotFieldBarLocation) {
        return @(idx);
     }
     else if (fieldEnum == CPTBarPlotFieldBarTip) {
        NSDate* date = [self.data.startDate dateByAddingTimeInterval:  (SECONDS_PER_DAY * idx)];
         for (YMBPSeries* bpEntry in self.data.bpSeries) {
         if ([bpEntry.date isUTCSameDay:date]) {
            if (bpEntry.systolic > 0)
              return @(bpEntry.systolic);
            else
              return nil;
         }
       }
     }
   }
    return nil;
  }


  @end

image 1

1 个答案:

答案 0 :(得分:0)

你走在正确的轨道上。对于具有血压的条形图使用一个绘图空间,对于心率的散点图使用第二绘图空间。将散点图的plotSymbol设置为所需的椭圆形状,并填充并将dataLineStyle设置为nil。这将在每个数据点绘制一个绘图符号,而它们之间没有连接线。