Я снова избиваю свою голову с помощью этой стены. У меня есть стрелка, основанная на this post. Когда я нажимаю вид, содержащий стрелку, мне нужно знать, содержит ли слой стрелки сенсорную точку. Я искал два дня для решения, но пока не нашел того, что работает. Если бы кто-то мог указать мне в правильном направлении, это было бы оценено тысячу раз.Обнаружить, если слой, который использует преобразование, содержит точку касания
@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
ли вы попробовать с 'CGPathContainsPoint (_arrowLayer.path, и Transf, расположение, NO)' 'transf' является CGAffineTransform из _arrowLayer – anhtu
я сделал, но он всегда возвращает ложь. –
Я также пробовал это: CGPoint transformPoint = CGPointApplyAffineTransform (местоположение, преобразование); if ([_arrowLayer containsPoint: transformPoint]) { [_delegate arrowTouched: self]; } –