I have been beating my head again the wall with this one. I have an arrow that is based upon this post. When I tap the view containing the arrow, I need to know if the arrow layer contains the touchpoint. I've searched for two days for a solution, but haven't found any that works yet. If someone could point me in the right direction, it would be appreciated a thousand times over.
@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