• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

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

[复制链接]
菜鸟教程小白 发表于 2022-12-13 10:16:48 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我一直在用这个敲我的头。我有一个基于 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-推荐答案


我找到了一个替代解决方案。 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/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap