Something I stumbled across while scratching my head over a similar problem is that CALayer uses containsPoint:
when you send it hitTest:
Its default behaviour is to test against bounds, but we can override and get it to check the alpha channel, and just use CALayer's built in hit-testing to handle the rest:
- (BOOL) containsPoint:(CGPoint)p
{
return CGRectContainsPoint(self.bounds, p) && !ImagePointIsTransparent(self.contents, p)) return YES;
}
There's a discussion of testing for a single pixel's alpha at Retrieving a pixel alpha value for a UIImage
This worked for my purposes:
static BOOL ImagePointIsTransparent(CGImageRef image, CGPoint p)
{
uint8_t alpha;
CGContextRef context = CGBitmapContextCreate(&alpha, 1, 1, 8, 1, NULL, kCGImageAlphaOnly);
CGContextDrawImage(context, CGRectMake(-p.x, -p.y, CGImageGetWidth(image), CGImageGetHeight(image)), image);
CGContextRelease(context);
return alpha == 0;
}
(If you're using renderInContext:
to draw to the CALayer rather than setting its contents property, then it's going to be more complicated. This might be useful in that case: http://www.cimgf.com/2009/02/03/record-your-core-animation-animation/)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…