hitTest перекрывающихся CALayers - PullRequest
       8

hitTest перекрывающихся CALayers

1 голос
/ 15 декабря 2011

У меня есть 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);
}
}

Моя проблема связана с областями, где границы треугольника перекрывают квадрат. Это приводит к тому, что треугольник регистрирует попадание, даже если оно находится за пределами путь треугольников. Это упрощенный пример (у меня может быть много перекрывающихся фигур, сложенных в виде) Есть ли способ перебрать все подслои и проверить каждый из них, чтобы увидеть, находится ли он под повернутой точкой? ИЛИ ЖЕ Есть ли способ, чтобы границы моих слоев совпадали с их путями, чтобы попадание происходило только в видимой области?

1 Ответ

11 голосов
/ 16 декабря 2011

Поскольку вы используете 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:] вам нужно передать точку в суперслое координатного пространства:

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