【问题标题】:hitTest overlapping CALayershitTest 重叠 CALayers
【发布时间】:2011-12-14 22:07:33
【问题描述】:

我有一个 UIView,其中包含我使用添加为子图层的 CALayers 制作的绘图。它是一个红色正方形,中间有一个蓝色三角形。我可以使用以下代码确定触摸了哪个形状:

CGPoint location = [gesture locationInView:self.view];
CALayer* layerThatWasTapped = [self.view.layer hitTest:location];
NSLog(@"Master Tap Location: %@", NSStringFromCGPoint(location));
NSLog(@"Tapped Layer Name: %@", layerThatWasTapped.name);
NSLog(@"Tapped Layer Parent: %@", layerThatWasTapped.superlayer.name);

int counter = layerThatWasTapped.superlayer.sublayers.count;
NSArray * subs =  layerThatWasTapped.superlayer.sublayers;

//Loop through all sublayers of the picture
for (int i=0; i<counter; i++) {
CALayer *layer = [subs objectAtIndex:i];
CAShapeLayer* loopLayer = (CAShapeLayer*)layerThatWasTapped.modelLayer;
CGPathRef loopPath = loopLayer.path;
CGPoint loopLoc = [gesture locationInView:cPage];        
loopLoc = [self.view.layer convertPoint:loopLoc toLayer:layer];
NSLog(@"loopLoc Tap Location: %@", NSStringFromCGPoint(loopLoc));

//determine if hit is on a layer
if (CGPathContainsPoint(loopPath, NULL, loopLoc, YES)) { 
NSLog(@"Layer %i Name: %@ Hit",i, layer.name);
} else {
NSLog(@"Layer %i Name: %@ No Hit",i, layer.name);
}
}

我的问题在于三角形边界与正方形重叠的区域。 这会导致三角形记录命中,即使命中超出了 三角形路径。这是一个简化的示例(我可能在视图中堆叠了许多重叠的形状) 有没有办法遍历所有子层并对每个子层进行测试以查看它是否位于分接点下方? 或者 有没有办法让我的图层的边界与它们的路径相匹配,这样点击只发生在可见区域?

【问题讨论】:

  • 你的三角形层是带有三角形图像的 CALayer,还是 CAShapeLayer?

标签: iphone objective-c core-animation calayer


【解决方案1】:

因为您使用的是 CAShapeLayer,所以这很容易。创建 CAShapeLayer 的子类并覆盖其 containsPoint: 方法,如下所示:

@implementation MyShapeLayer

- (BOOL)containsPoint:(CGPoint)p
{
    return CGPathContainsPoint(self.path, NULL, p, false);
}

@end

确保无论您在何处分配 CAShapeLayer,都将其更改为分配 MyShapeLayer

CAShapeLayer *triangle = [MyShapeLayer layer];  // this way
CAShapeLayer *triangle = [[MyShapeLayer alloc] init]; // or this way

最后要记住,调用-[CALayer hitTest:]时,需要传入superlayer的坐标空间中的一个点:

CGPoint location = [gesture locationInView:self.view];
CALayer *myLayer = self.view.layer;
location = [myLayer.superlayer convertPoint:location fromLayer:myLayer];
CALayer* layerThatWasTapped = [myLayer hitTest:location];

【讨论】:

  • 谢谢!我试过类似的东西,现在我意识到我是子类化 CALayer 而不是 CAShapeLayer。谢谢!!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-15
  • 1970-01-01
  • 1970-01-01
  • 2014-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多