Question

I am working on a map functionality. The map is built up out of multiple CAShapeLayers with CGPaths from calculated coordinates. I have a clipping problem. Look below on the screenshot where Alaska is badly clipped. The coordinates of the Alaska path extend beyond the bounds of my container layer. In effect, if i make my container layer big enough the clipping effect is gone (of course).

You see a dark line because at the bottom of Alaska is solid from left to right. Also the line is darker than the rest of the map because the map has opacity (it gets darker because it adds up).

I drilled down into the problem and i have narrowed it down to the single big polygon (there are not other polygons responsible for the clipping error).

Sample screenshot

As a workaround, i make the layer bigger to hide the line, then make the UIView smaller again to hide the line.

I'd like to know what is causing the issue instead of working with workarounds.

Was it helpful?

Solution

After a lot of digging, i managed to find an answer to my own question.

I was rendering the layers to an UIImage for improved performance. The background layer was scaled up by a UIScrollView and then several things went wrong:

  1. Apparently, setting masksToBounds:YES has no effect when using renderInContext, just as it does with the mask property of a CALayer. MasksToBounds (or clipToBounds) only applies to childlayers.
  2. When scaling a bitmap, be sure to include integral values to the scale argument of UIGraphicsBeginImageContextWithOptions. If not, the image will have fractional sizes, e.g. 24.2323 x 34.3290. Btw, that scale argument is used to create amazing detail on Retina screens, but it can be misused to zoom in on CAShapeLayer drawings.
  3. When using fractional size images as a background layer, you get distortion at the edge.

The clipping effect disappeared after i updated my layer to image function. This one did the trick:

- (UIImage *)getImageWithSize:(CGSize)size opaque:(bool)opaque contentScale:(CGFloat)scale
{
    CGContextRef context;

    size = CGSizeMake(ceilf(size.width), ceilf(size.height));
    scale = roundf(scale);

    UIGraphicsBeginImageContextWithOptions(size, opaque, scale);
    context = UIGraphicsGetCurrentContext();
    [self renderInContext:context];
    UIImage *outputImg = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return outputImg;
}

Using ceilf, roundf, or floorf didn't really matter. As long as you lose the fractions.

Sorry if my stupidity wasted any of your time, but perhaps others have the same issue.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top