我一直在用这个敲我的头。我有一个基于 this post 的箭头.当我点击包含箭头的 View 时,我需要知道箭头层是否包含接触点。我已经搜索了两天的解决方案,但还没有找到任何可行的方法。如果有人能指出我正确的方向,那将不胜感激一千倍。
@implementation ArrowView
{
CGFloat headLength;
UIBezierPath *path;
}
- (id) initWithFrameCGRect)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 actionselector(tapped];
[self addGestureRecognizer:tap];
}
return self;
}
- (void) tapped: (UITapGestureRecognizer *) sender {
CGPoint location = [sender locationInView: sender.view];
if ([_arrowLayer containsPoint:location]) {
[_delegate arrowTouched:self];
}
}
- (void) drawRectCGRect)rect {
[super drawRect:rect];
[_arrowLayer removeFromSuperlayer];
[_bottomButtonLayer removeFromSuperlayer];
[_topButtonLayer removeFromSuperlayer];
_tailWidth = 5 + _weight;
_headWidth = 25 + _weight;
headLength = 40;
path = [UIBezierPath dqd_bezierPathWithArrowFromPointCGPoint)_startPoint
toPointCGPoint)_endPoint
tailWidthCGFloat)_tailWidth
headWidthCGFloat)_headWidth
headLengthCGFloat)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_bezierPathWithArrowFromPointCGPoint)startPoint toPointCGPoint)endPoint tailWidthCGFloat)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
Best Answer-推荐答案 strong>
我找到了一个替代解决方案。 SpaceDog 让我以不同的方式思考这种情况。我只需要知道是否触摸了有颜色的区域。我找到了这篇文章并将其翻译为Objective C。它工作得很好。虽然我更喜欢检测点在箭头内,但这也适用于我的目的。谢谢大家的回复。我很感激。
Post I got the code below from.
- (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;
}
关于ios - 检测使用变换的层是否包含接触点,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/32367713/
|