Search code examples
iosxcodecocoa-touchdrawingcalayer

Drawing on a CA Layer


I have a CALayer that's a sublayer of an ImageView. This shows an image, which the user can resize/rotate etc.

I want to be able to let the user draw on top of the image (to erase the image) with PanGesture - this works fine if the image is original size (user hasn't tried to resize/rotate), but as soon as the user resizes/rotates and tries again, the line that he/she can draw on the image will scale with the image (i.e. if the user makes halves the size of the image layer, the drawing line will be halved, and if the user rotates the image layer by 45 degrees, panning up will draw a diagonal line).

I'm currently trying to do this by drawing and then setting the layer.contents with the newly created self.image2 (image2Position is the current position of the layer on the screen):

  UIGraphicsBeginImageContextWithOptions(self.image2.size, NO, 0.0);
    [self.image2 drawInRect:CGRectMake(0, 0, self.image2.size.width, self.image2.size.height)];

    [eraser drawAtPoint:CGPointAdd2(CGPointAdd(currentPoint, CGPointMake(-center.x, -center.y)), CGPointMake(-self.image2Position.x, -self.image2Position.y)) blendMode:kCGBlendModeDestinationOut alpha:1];

    self.image2 = UIGraphicsGetImageFromCurrentImageContext();

How can I ensure that the user can draw a line of the same size and in the same coordinate system, no matter how he/she rotates/resizes the image?


Solution

  • Calculate scale of your image eg. 0.5 and adjust lineWidth (I'm assuming that you use UIBezierPath, it's faster than non-optimized CGPath) to it. OK that's easy. Now you need to get transform of your CALayer and rotate your UIBezierPath accordingly. It's a bit hard due to size etc etc.

    • Check if a point is inside CALayer using convertPoint: toLayer: or convertPoint:fromLayer:

    • Use this converted point to draw this UIBezierPath.