Ios 检测使用变换的层是否包含接触点

Ios 检测使用变换的层是否包含接触点,ios,objective-c,Ios,Objective C,我又用这个把头撞到墙上了。我有一支箭,它是以我为基础的。当我点击包含箭头的视图时,我需要知道箭头层是否包含接触点。我已经找了两天的解决方案,但还没有找到任何有效的。如果有人能给我指出正确的方向,我将不胜感激 @implementation ArrowView { CGFloat headLength; UIBezierPath *path; } - (id) initWithFrame:(CGRect)frame withColor: (UIColor *) color wit

我又用这个把头撞到墙上了。我有一支箭,它是以我为基础的。当我点击包含箭头的视图时,我需要知道箭头层是否包含接触点。我已经找了两天的解决方案,但还没有找到任何有效的。如果有人能给我指出正确的方向,我将不胜感激

@implementation ArrowView
{
    CGFloat headLength;
    UIBezierPath *path;
}

- (id) initWithFrame:(CGRect)frame withColor: (UIColor *) color withWeight: (CGFloat) weight withStartPoint: (CGPoint) startPoint withEndPoint: (CGPoint) endPoint {

    if (self = [super initWithFrame:frame]) {
        _arrowColor = color;
        _weight = weight;
        _startPoint = startPoint;
        _endPoint = endPoint;

        self.userInteractionEnabled = YES;

        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)];
        [self addGestureRecognizer:tap];
    }

    return self;
}

- (void) tapped: (UITapGestureRecognizer *) sender {
    CGPoint location = [sender locationInView: sender.view];

    if ([_arrowLayer containsPoint:location]) {
        [_delegate arrowTouched:self];
    }
}

- (void) drawRect:(CGRect)rect {
    [super drawRect:rect];

    [_arrowLayer removeFromSuperlayer];
    [_bottomButtonLayer removeFromSuperlayer];
    [_topButtonLayer removeFromSuperlayer];

    _tailWidth = 5 + _weight;
    _headWidth = 25 + _weight;
    headLength = 40;

    path = [UIBezierPath dqd_bezierPathWithArrowFromPoint:(CGPoint)_startPoint
                                                  toPoint:(CGPoint)_endPoint
                                                tailWidth:(CGFloat)_tailWidth
                                                headWidth:(CGFloat)_headWidth
                                               headLength:(CGFloat)headLength];
    [path setLineWidth:_weight];

    CGFloat width = _endPoint.x - _startPoint.x;
    CGFloat height = _endPoint.y - _startPoint.y;

    CGFloat offset = 5;
    if (ABS(width) < offset) {
        width = width > 0 ? offset : -offset;
    }

    if (ABS(height) < offset) {
        height = height > 0 ? offset : -offset;
    }

    _arrowLayer = [CAShapeLayer layer];
    _arrowLayer.bounds = CGRectMake(_startPoint.x, _startPoint.y, width, height);
    _arrowLayer.position = CGPointMake(((_endPoint.x - _startPoint.x) / 2), (_endPoint.y - _startPoint.y) / 2);

    _arrowLayer.path = path.CGPath;
    _arrowLayer.fillColor = _arrowColor.CGColor;
    //_arrowLayer.backgroundColor = [UIColor greenColor].CGColor;

    if (!_isSelected) {
        _arrowLayer.strokeColor = _arrowColor.CGColor;
    } else {
        if (_arrowColor != [UIColor blackColor]) {
            _arrowLayer.strokeColor = [UIColor blackColor].CGColor;
        } else {
            _arrowLayer.strokeColor = [UIColor whiteColor].CGColor;
        }
    }

    _arrowLayer.borderColor = [UIColor whiteColor].CGColor;
    _arrowLayer.borderWidth = 1;

    [self.layer addSublayer:_arrowLayer];
}

- (void) setIsSelected: (BOOL) isSelected {
    _isSelected = isSelected;
    [self setNeedsDisplay];
}

- (void) updateStartPoint: (CGPoint) startPoint {
    _startPoint = startPoint;
    [self setNeedsDisplay];
}

- (void) updateEndPoint: (CGPoint) endPoint {
    _endPoint = endPoint;
    [self setNeedsDisplay];
}

- (void) updateColor: (UIColor *) color {
    _arrowColor = color;
    [self setNeedsDisplay];
}

- (void) updateWeight: (CGFloat) weight {
    _weight = weight;
    [self setNeedsDisplay];
}

@end

#define kArrowPointCount 7

@implementation UIBezierPath (dqd_arrowhead)

+ (UIBezierPath *)dqd_bezierPathWithArrowFromPoint:(CGPoint)startPoint toPoint:(CGPoint)endPoint tailWidth:(CGFloat)tailWidth headWidth:(CGFloat)headWidth headLength:(CGFloat)headLength {

    CGFloat length = hypotf(endPoint.x - startPoint.x, endPoint.y - startPoint.y);
    CGPoint points[kArrowPointCount];
    [self dqd_getAxisAlignedArrowPoints:points forLength:length tailWidth:tailWidth headWidth:headWidth headLength:headLength];
    CGAffineTransform transform = [self dqd_transformForStartPoint:startPoint endPoint:endPoint length:length];
    CGMutablePathRef cgPath = CGPathCreateMutable();
    CGPathAddLines(cgPath, &transform, points, sizeof points / sizeof *points);
    CGPathCloseSubpath(cgPath);
    UIBezierPath *uiPath = [UIBezierPath bezierPathWithCGPath:cgPath];
    CGPathRelease(cgPath);

    return uiPath;
}

+ (void)dqd_getAxisAlignedArrowPoints:(CGPoint[kArrowPointCount])points
                            forLength:(CGFloat)length
                            tailWidth:(CGFloat)tailWidth
                            headWidth:(CGFloat)headWidth
                           headLength:(CGFloat)headLength {
    CGFloat tailLength = length - headLength;
    points[0] = CGPointMake(0, tailWidth / 2);
    points[1] = CGPointMake(tailLength, tailWidth / 2);
    points[2] = CGPointMake(tailLength, headWidth / 2);
    points[3] = CGPointMake(length, 0);
    points[4] = CGPointMake(tailLength, -headWidth / 2);
    points[5] = CGPointMake(tailLength, -tailWidth / 2);
    points[6] = CGPointMake(0, -tailWidth / 2);
}

+ (CGAffineTransform)dqd_transformForStartPoint:(CGPoint)startPoint
                                       endPoint:(CGPoint)endPoint
                                         length:(CGFloat)length {
    CGFloat cosine = (endPoint.x - startPoint.x) / length;
    CGFloat sine = (endPoint.y - startPoint.y) / length;
    return (CGAffineTransform){ cosine, sine, -sine, cosine, startPoint.x, startPoint.y };
}

@end
@实现箭头视图
{
头长;
UIBezierPath*路径;
}
-(id)initWithFrame:(CGRect)frame with color:(UIColor*)color with weight:(CGFloat)weight with startPoint:(CGPoint)startPoint with endPoint:(CGPoint)endPoint{
if(self=[super initWithFrame:frame]){
_箭头颜色=颜色;
_重量=重量;
_起始点=起始点;
_终点=终点;
self.userInteractionEnabled=是;
UITapGestureRecognizer*点击=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(点击:)];
[自选地址识别器:点击];
}
回归自我;
}
-(无效)点击:(UITapgestureRecognitor*)发送方{
CGPoint location=[sender locationInView:sender.view];
if([\u arrowLayer containsPoint:location]){
[_:self];
}
}
-(void)drawRect:(CGRect)rect{
[超级drawRect:rect];
[_arrowLayer从SuperLayer移除];
[_bottombuttonlayerremovefromsuperlayer];
[_topButtonLayer从SuperLayer移除];
_尾宽=5+_重量;
_头部宽度=25+_重量;
头长=40;
path=[UIBezierPath dqd\U BEZIERPATH WITHARROWFROMPOINT:(CGPoint)\U startPoint
拓扑点:(CGPoint)\端点
尾宽:(CGFloat)\尾宽
头宽:(CGFloat)\头宽
头长:(CGFloat)头长];
[路径设置线宽:_权重];
CGFloat width=_endPoint.x-_startPoint.x;
CGFloat height=_endPoint.y-_startPoint.y;
CGFloat偏移=5;
if(绝对值(宽度)<偏移量){
宽度=宽度>0?偏移量:-偏移量;
}
如果(ABS(高度)<偏移量){
高度=高度>0?偏移量:-偏移量;
}
_arrowLayer=[CAShapeLayer层];
_arrowLayer.bounds=CGRectMake(_startPoint.x,_startPoint.y,宽度,高度);
_arrowLayer.position=CGPointMake(((_endPoint.x-_startPoint.x)/2),(_endPoint.y-_startPoint.y)/2);
_arrowLayer.path=path.CGPath;
_arrowLayer.fillColor=\u arrowColor.CGColor;
//_arrowLayer.backgroundColor=[UIColor greenColor].CGColor;
如果(!\u被选中){
_arrowLayer.strokeColor=\u arrowColor.CGColor;
}否则{
如果(_arrowColor!=[UIColor blackColor]){
_arrowLayer.strokeColor=[UIColor blackColor].CGColor;
}否则{
_arrowLayer.strokeColor=[UIColor whiteColor].CGColor;
}
}
_arrowLayer.borderColor=[UIColor whiteColor].CGColor;
_arrowLayer.borderWidth=1;
[self.layer addSublayer:_arrowLayer];
}
-(无效)setIsSelected:(BOOL)isSelected{
_isSelected=isSelected;
[自我设置需要显示];
}
-(void)updateStartPoint:(CGPoint)startPoint{
_起始点=起始点;
[自我设置需要显示];
}
-(void)updateEndPoint:(CGPoint)端点{
_终点=终点;
[自我设置需要显示];
}
-(void)updateColor:(UIColor*)颜色{
_箭头颜色=颜色;
[自我设置需要显示];
}
-(无效)更新权重:(CGFloat)权重{
_重量=重量;
[自我设置需要显示];
}
@结束
#定义kArrowPointCount 7
@实现UIBezierPath(dqd_箭头)
+(UIBezierPath*)DQDU BEZIERPATH带箭头FROMPOINT:(CGPoint)startPoint toPoint:(CGPoint)端点尾宽:(CGFloat)尾宽头宽:(CGFloat)头宽头长:(CGFloat)头长{
CGFloat length=hypotf(endPoint.x-startPoint.x,endPoint.y-startPoint.y);
CGPoint points[kArrowPointCount];
[自dqd_获取轴对齐箭头点:长度点:长度尾宽:尾宽头宽:头宽头长:头长];
CGAffineTransform transform=[self-dqd_transformForStartPoint:startPoint端点:端点长度:长度];
CGMutablePathRef cgPath=CGPathCreateMutable();
CGPathAddLines(cgPath、变换、点、sizeof点/sizeof*点);
CGPathCloseSubpath(cgPath);
UIBezierPath*uiPath=[UIBezierPath BEZIERPATH WITHCGPATH:cgPath];
cgPath释放(cgPath);
返回路径;
}
+(无效)dqd_getAxisAlignedArrowPoints:(CGPoint[kArrowPointCount])点
forLength:(CGFloat)长度
尾宽:(CGFloat)尾宽
头宽:(CGFloat)头宽
头长:(CGFloat)头长{
CGFloat tailLength=长度-头长;
点[0]=CGPointMake(0,尾宽/2);
点[1]=CGPointMake(尾长、尾宽/2);
点[2]=CGPointMake(尾长、头宽/2);
点[3]=CGPointMake(长度,0);
点[4]=CGPointMake(尾长-头宽/2);
点[5]=CGPointMake(尾长,-尾宽/2);
点[6]=CGPointMake(0,-尾宽/2);
}
+(CGAffineTransform)dqd_变换起点:(CGPoint)起点
端点:(CGPoint)端点
长度:(CGFloat)长度{
CGFloat余弦=(endPoint.x-startPoint.x)/长度;
CGFloat sine=(endPoint.y-startPoint.y)/长度;
返回(CGAffineTransform){cosine,sine,-sine,cosine,startPoint.x,startPoint.y};
}
@结束

如果视图的大小与箭头相同,并且被点击:被触发,则表示您已用箭头点击视图

您不需要这样做:

- (void) tapped: (UITapGestureRecognizer *) sender {
    CGPoint location = [sender locationInView: sender.view];

    if ([_arrowLayer containsPoint:location]) {
        [_delegate arrowTouched:self];
    }
}
您可以选择:

- (void) tapped: (UITapGestureRecognizer *) sender {

  NSLog(@"arrow was tapped");

}

我找到了另一个解决办法。太空狗让我对情况有了不同的看法。我只想知道一个有科罗拉多的地区
- (void) tapped: (UITapGestureRecognizer *) sender {
    CGPoint location = [sender locationInView: sender.view];
    CGFloat p = [self alphaFromPoint:location];
    if (p > 0) {
        [_delegate arrowTouched:self];
    }
}

- (CGFloat) alphaFromPoint: (CGPoint) point {
    UInt8 pixel[4] = {0,0,0,0};
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo alphaInfo = (CGBitmapInfo)kCGImageAlphaPremultipliedLast;


    CGContextRef context = CGBitmapContextCreate(&pixel, 1, 1, 8, 4, colorSpace, alphaInfo);

    CGContextTranslateCTM(context, -point.x, -point.y);

    [self.layer renderInContext:context];
    CGFloat floatAlpha = pixel[3];
    return floatAlpha;
}