SHGraphLineView 移除一个图

SHGraphLineView remove a plot

我正在使用这个名为 SHLineGraphView 的 class,它运行良好,但我有一个问题,他们没有实现删除情节的方法。现在我必须这样做,但我想不出正确的方法。

他们是这样画情节的:

- (void)addPlot:(SHPlot *)newPlot;
{
  if(nil == newPlot) {
    return;
  }

  if(_plots == nil){
    _plots = [NSMutableArray array];
  }
  [_plots addObject:newPlot];
}

- (void)drawPlot:(SHPlot *)plot {

  NSDictionary *theme = plot.plotThemeAttributes;

  //
  CAShapeLayer *backgroundLayer = [CAShapeLayer layer];
  backgroundLayer.frame = self.bounds;
  backgroundLayer.fillColor = ((UIColor *)theme[kPlotFillColorKey]).CGColor;
  backgroundLayer.backgroundColor = [UIColor clearColor].CGColor;
  [backgroundLayer setStrokeColor:[UIColor clearColor].CGColor];
  [backgroundLayer setLineWidth:((NSNumber *)theme[kPlotStrokeWidthKey]).intValue];

  CGMutablePathRef backgroundPath = CGPathCreateMutable();

  //
  CAShapeLayer *circleLayer = [CAShapeLayer layer];
  circleLayer.frame = self.bounds;
  circleLayer.fillColor = ((UIColor *)theme[kPlotPointFillColorKey]).CGColor;
  circleLayer.backgroundColor = [UIColor clearColor].CGColor;
  [circleLayer setStrokeColor:((UIColor *)theme[kPlotPointFillColorKey]).CGColor];
  [circleLayer setLineWidth:((NSNumber *)theme[kPlotStrokeWidthKey]).intValue];

  CGMutablePathRef circlePath = CGPathCreateMutable();

  //
  CAShapeLayer *graphLayer = [CAShapeLayer layer];
  graphLayer.frame = self.bounds;
  graphLayer.fillColor = [UIColor clearColor].CGColor;
  graphLayer.backgroundColor = [UIColor clearColor].CGColor;
  [graphLayer setStrokeColor:((UIColor *)theme[kPlotStrokeColorKey]).CGColor];
  [graphLayer setLineWidth:((NSNumber *)theme[kPlotStrokeWidthKey]).intValue];

  CGMutablePathRef graphPath = CGPathCreateMutable();

  double yRange = [_yAxisRange doubleValue]; // this value will be in dollars
  double yIntervalValue = yRange / INTERVAL_COUNT;

  //logic to fill the graph path, ciricle path, background path.
  [plot.plottingValues enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    NSDictionary *dic = (NSDictionary *)obj;

    __block NSNumber *_key = nil;
    __block NSNumber *_value = nil;

    [dic enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
      _key = (NSNumber *)key;
      _value = (NSNumber *)obj;
    }];

    int xIndex = [self getIndexForValue:_key forPlot:plot];

    //x value
    double height = self.bounds.size.height - BOTTOM_MARGIN_TO_LEAVE;
    double y = height - ((height / ([_yAxisRange doubleValue] + yIntervalValue)) * [_value doubleValue]);
    (plot.xPoints[xIndex]).x = ceil((plot.xPoints[xIndex]).x);
    (plot.xPoints[xIndex]).y = ceil(y);
  }];

  //move to initial point for path and background.
  CGPathMoveToPoint(graphPath, NULL, _leftMarginToLeave, plot.xPoints[0].y);
  CGPathMoveToPoint(backgroundPath, NULL, _leftMarginToLeave, plot.xPoints[0].y);

  int count = _xAxisValues.count;
  for(int i=0; i< count; i++){
    CGPoint point = plot.xPoints[i];
    CGPathAddLineToPoint(graphPath, NULL, point.x, point.y);
    CGPathAddLineToPoint(backgroundPath, NULL, point.x, point.y);
    CGPathAddEllipseInRect(circlePath, NULL, CGRectMake(point.x - 2.5, point.y - 2.5, 5, 5));
  }

  //move to initial point for path and background.
  CGPathAddLineToPoint(graphPath, NULL, _leftMarginToLeave + PLOT_WIDTH, plot.xPoints[count -1].y);
  CGPathAddLineToPoint(backgroundPath, NULL, _leftMarginToLeave + PLOT_WIDTH, plot.xPoints[count - 1].y);

  //additional points for background.
  CGPathAddLineToPoint(backgroundPath, NULL, _leftMarginToLeave + PLOT_WIDTH, self.bounds.size.height - BOTTOM_MARGIN_TO_LEAVE);
  CGPathAddLineToPoint(backgroundPath, NULL, _leftMarginToLeave, self.bounds.size.height - BOTTOM_MARGIN_TO_LEAVE);
  CGPathCloseSubpath(backgroundPath);

  backgroundLayer.path = backgroundPath;
  graphLayer.path = graphPath;
  circleLayer.path = circlePath;

  //animation
  CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
  animation.duration = 1;
  animation.fromValue = @(0.0);
  animation.toValue = @(1.0);
  [graphLayer addAnimation:animation forKey:@"strokeEnd"];

  backgroundLayer.zPosition = 0;
  graphLayer.zPosition = 1;
  circleLayer.zPosition = 2;

  [self.layer addSublayer:graphLayer];
  [self.layer addSublayer:circleLayer];
  [self.layer addSublayer:backgroundLayer];

    NSUInteger count2 = _xAxisValues.count;
    for(int i=0; i< count2; i++){
        CGPoint point = plot.xPoints[i];
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        btn.backgroundColor = [UIColor clearColor];
        btn.tag = i;
        btn.frame = CGRectMake(point.x - 20, point.y - 20, 40, 40);
        [btn addTarget:self action:@selector(clicked:) forControlEvents:UIControlEventTouchUpInside];
        objc_setAssociatedObject(btn, kAssociatedPlotObject, plot, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    [self addSubview:btn];
    }
}

这就是我添加的内容,但就是不知道如何真正删除情节:

- (void)removePlot:(SHPlot *)plot
{
    if (nil == plot) {
        return;
    }

    if (_plots == nil) {
        return;
    }

    [_plots removeObject:plot];
    [self removePlotFromView:plot];
}

这是您需要添加到 SHLineGraphView.m 文件中的内容。 此方法将删除所有添加到您的图形视图上的图。

- (void)removeAllPlots {
    for (UIView *view in self.subviews) {
        view.layer.sublayers = nil;
        [view removeFromSuperview];
    }

    self.layer.sublayers = nil;
}

要删除特定图,首先需要为 graphLayer、circleLayer 和 backgroundLayer 提供唯一标签。

您可以通过在 drawPlot: 方法中添加以下代码来实现。

    [graphLayer setValue:[NSNumber numberWithInteger:[_plots indexOfObject:plot]]  forKey:@"PLTag"];
    [circleLayer.frame setValue:[NSNumber numberWithInteger:[_plots indexOfObject:plot]] forKey:@"PLTag"];
    [backgroundLayer setValue:[NSNumber numberWithInteger:[_plots indexOfObject:plot]] forKey:@"PLTag"];

然后,添加此方法以删除特定情节:

- (void)removePlot:(SHPlot *)plot
{
    if (plot == nil)
        return;
    else if (_plots == nil)
        return;

    for (CALayer *layer in self.layer.sublayers) {
        if ([[layer valueForKey:@"PLTag"] isEqualToNumber:[NSNumber numberWithInteger:[_plots indexOfObject:plot]]]) {
            [layer removeFromSuperlayer];
        }
    }
}

希望对你有帮助。

因此,根据@Tejvansh Singh Chhabra 的回答,我设法找到了解决方案:

首先,我已经将这两种新方法添加到 SHGraphLineView.h:

/**
 *  this methods will remove a plot from the graph.
 *
 *  @param plot the Plot that you want to remove from the Graph.
 */
- (void)removePlot:(SHPlot *)plot;


/**
 *  this methods will draw a new plot on the graph.
 *
 *  @param plot the Plot that you want to draw on the Graph.
 */
- (void)drawNewPlot:(SHPlot*)plot;

并在主文件中实现它们:

- (void)removePlot:(SHPlot *)plot
{
    if (plot == nil) {
        return;
    }
    else if (_plots == nil) {
        return;
    }

    for (CALayer *layer in [self.layer.sublayers copy])
    {
        if ([layer valueForKey:@"PLTag"] != nil)
        {
            NSString *tag = [layer valueForKey:@"PLTag"];
            NSString *plotIndex = [NSString stringWithFormat:@"%ld", (long)plot.plotIndex];
            if ([tag isEqualToString:plotIndex])
            {
                [layer removeFromSuperlayer];
            }
        }
    }

    [_plots removeObject:plot];
}

- (void)drawNewPlot:(SHPlot*)plot
{
    if (nil == plot) {
        return;
    }

    if (_plots == nil) {
        _plots = [NSMutableArray array];
    }

    [_plots addObject:plot];
    [self xPointWithoutDrawingForPlot:plot];
    [self drawPlot:plot];
}

现在有另一种方法可以为绘图创建 x 点,但没有标签和所有其他在您第一次构建图表时用它绘制的东西:

- (void)xPointWithoutDrawingForPlot:(SHPlot*)plot
{
    int xIntervalCount = _xAxisValues.count;
    double xIntervalInPx = PLOT_WIDTH / _xAxisValues.count;

    //initialize actual x points values where the circle will be
    plot.xPoints = calloc(sizeof(CGPoint), xIntervalCount);

    for(int i=0; i < xIntervalCount; i++)
    {
        CGPoint currentLabelPoint = CGPointMake((xIntervalInPx * i) + _leftMarginToLeave, self.bounds.size.height - BOTTOM_MARGIN_TO_LEAVE);
        CGRect xLabelFrame = CGRectMake(currentLabelPoint.x , currentLabelPoint.y, xIntervalInPx, BOTTOM_MARGIN_TO_LEAVE);
        plot.xPoints[i] = CGPointMake((int) xLabelFrame.origin.x + (xLabelFrame.size.width /2) , (int) 0);
    }
}

另外一个很重要的是在第一次绘制的plot的CAShapeLayer对象中添加一个valueForKey,我们需要在这个方法中添加:

- (void)drawPlot:(SHPlot *)plot;

这 3 行:

[graphLayer setValue:[NSString stringWithFormat:@"%ld", (long)plot.plotIndex]  forKey:@"PLTag"];
[circleLayer setValue:[NSString stringWithFormat:@"%ld", (long)plot.plotIndex] forKey:@"PLTag"];
[backgroundLayer setValue:[NSString stringWithFormat:@"%ld", (long)plot.plotIndex] forKey:@"PLTag"];

最后一件事,对于SHPlot class我们需要添加一个NSInteger来指示这个特定地块的索引,你需要在第一次构建时设置它剧情

SHPlot.h

/**
 *  index for plot for identification
 */
@property (assign, nonatomic) NSInteger plotIndex;

尽情享受吧! :)