使用CALayer内容的alpha属性使用CALayer进行测试

时间:2010-05-31 14:10:09

标签: cocoa calayer

我正在使用Cocoa为Mac编写游戏。我目前正在实施热门测试,并发现CALayer提供了热门测试,但似乎没有实现alpha属性。由于我有时很多CALayers堆叠在一起,我真的需要找到一种方法来确定用户实际上要点击的内容。

我在想,如果我能以某种方式得到一个包含指向包含点击点的所有CALayer的指针的数组,我可以通过它们过滤一些方法。然而,我到目前为止创建数组的唯一方法是:

NSMutableArray* anArrayOfLayers = [NSMutableArray array];
    for (CALayer* aLayer in mapLayer.sublayers)
    {
        if ([aLayer containsPoint:mouseCoord])
            [anArrayOfLayers addObject:aLayer];
    }

然后按照CALayer的z值对数组进行排序,然后检查位置处的像素是否为alpha。然而,在排序和alpha检查之间,这似乎是一个令人难以置信的性能猪。 (你怎么能检查阿尔法?)

有没有办法做到这一点?

1 个答案:

答案 0 :(得分:10)

我在遇到类似问题时偶然发现的一件事是CALayer在您发送containsPoint:时使用hitTest:

它的默认行为是针对边界进行测试,但是我们可以覆盖并使其检查alpha通道,并使用CALayer的内置命中测试来处理其余部分:

- (BOOL) containsPoint:(CGPoint)p 
{
    return CGRectContainsPoint(self.bounds, p) && !ImagePointIsTransparent(self.contents, p)) return YES;
}

讨论了在Retrieving a pixel alpha value for a UIImage

测试单个像素的alpha值

这符合我的目的:

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;
}

(如果您使用renderInContext:绘制到CALayer而不是设置其内容属性,那么它会更复杂。在这种情况下这可能很有用:http://www.cimgf.com/2009/02/03/record-your-core-animation-animation/