0

I'm drawing a graph using a CGPath applied to a CAShapeLayer. The graph itself is drawn just fine, but I want to add a gradient underneath it afterwards. My problem is that the path is closed with a straight line going from the last point to the first point (see below) – this would make a gradient fill look totally ridiculous.

enter image description here

As far as I can see, the only way to circumvent this issue is to draw two additional lines: one from the last point of the graph to the bottom-right corner, and from there, another one to the bottom-left corner. This would close the path off nicely, but it would add a bottom line to the graph, which I don't want.

If I were using CGContext, I could easily solve this by changing the stroke color to transparent for the last two lines. However, with the code below, I don't see how that would be possible.

CGMutablePathRef graphPath = CGPathCreateMutable();

for (NSUInteger i = 0; i < self.coordinates.count; i++) {
    CGPoint coordinate = [self.coordinates[i] CGPointValue];

    if (!i) {
        CGPathMoveToPoint(graphPath, NULL, coordinate.x, coordinate.y);
    } else {
        CGPathAddLineToPoint(graphPath, NULL, coordinate.x, coordinate.y);
    }
}

CAShapeLayer *graphLayer = [CAShapeLayer new];
graphLayer.path = graphPath;
graphLayer.strokeColor = [UIColor whiteColor].CGColor;
graphLayer.fillColor = [UIColor redColor].CGColor;

[self.layer addSublayer:graphLayer];

I hope you guys can help me out!

Update: You suggest that I could create a CAGradientLayer, and then apply the graph layer as its mask. I don't see how that would work, though, when the graph/path looks the way it does. I have replaced the image above with another graph that hopefully illustrates the problem better (note that I've given the CAShapeLayer a red fill). As I see it, if I were to apply above layer as the mask of a CAGradientLayer, some of the gradient would lie above the graph, some it below. What I want is for all of the gradient to be placed right beneath the graph.

wstr
  • 910
  • 2
  • 13
  • 23
  • Here is your solution: http://stackoverflow.com/a/7264787/312312 – Lefteris Sep 10 '15 at 19:32
  • Do you actually want that red fill? Or do you just want the area under the graph filled with the gradient, and no visible diagonal? – rob mayoff Sep 10 '15 at 22:45
  • @robmayoff I don't want the red fill, no; just a gradient that starts right beneath the graph line. – wstr Sep 11 '15 at 08:03
  • @Lefteris Please see my update. I don't think the solution you link to is applicable to this particular problem. – wstr Sep 12 '15 at 15:57

2 Answers2

0

Maybe I'm not understanding the problem correctly, but if you're looking to add a consistent gradient, couldn't you create a gradient layer and then make your graphLayer be that layer's mask?

Figure out whatever the min max bounds of your coordinates, create a CAGradientLayer that size, configure it however you might like and then, apply your graphLayer as it's mask. Then add the new CAGradientLayer to your self.layer.

CAGradientLayer *gradientLayer = [CAGradientLayer layer];
// ... Configure the gradientLayer colors / locations / size / etc...
gradientLayer.mask = graphLayer;

[self.layer addSubLayer:gradientLayer];

This doesn't take into account the stroke, but it shouldn't be difficult to apply that as well if that's important.

0

I solved the problem by creating two separate paths: One for the graph (as shown in my original post), and one that starts in the lower-right corner, moves in a straight line to the lower-left corner, and from there follows the same path as the graph. By doing so, the path gets closed off nicely, since the graph ends at the same x-coordinate as where the path started.

From there, I applied the second path to a CAShapeLayer, and then used this layer as the mask of a gradient layer.

wstr
  • 910
  • 2
  • 13
  • 23