首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >检测旋转CAShapeLayer上的接触

检测旋转CAShapeLayer上的接触
EN

Stack Overflow用户
提问于 2013-07-16 14:20:58
回答 1查看 658关注 0票数 2

我试图在自定义CALayer中使用自定义UIView实现UI元素。

基本上,用户用他/她的手指在一个圆圈上移动一个滑块,所以我有一个交互层,然后是一个CAShapeLayer类型的子层,它表示滑块本身。我想,移动滑块的最简单的方法就是旋转CAShapeLayer的z轴。

虽然滑块确实按预期在视觉上旋转,但当我对接收到的触点执行命中测试时,“可命中”区域仍然驻留在滑块的预旋转位置。这就好像CAShapeLayer旋转的视觉效果与嵌入在层中的UIBezierPath解耦,从而形成层的path属性,因为我使用该路径与CGPathContainsPoint()一起识别滑块上的触点。

总的来说,我对核心图形( Core Graphics )还不熟悉,所以我认为这里可能有一个我没有正确设置的属性,但我很难弄清楚它是什么。

以下是代码:

TouchableLayer.m

代码语言:javascript
复制
@interface TouchableLayer ()
{
    CAShapeLayer *_slider;    // The interactive slider that gets moved around the circle.
}

-(id) initWithPosition:(NSInteger) position // Designated initializer for this layer.
{
    if ( self = [super init] )
    {
        _slider = [CAShapeLayer layer];

        _slider.fillColor = [UIColor blackColor].CGColor;

        [self addSublayer:_slider];
    }

    return self;
}

-(void) setFrame:(CGRect)frame
{
    [super setFrame:frame];

    _slider.frame = frame;

    // This path is currently hardcoded to be in the right starting spot according to
    //    other UI elements, but the magic numbers will go away once I figure out this
    //    rotation issue.
    _slider.path = [UIBezierPath bezierPathWithRect:CGRectMake(self.bounds.size.width-47, self.bounds.size.height/2-5, 30.0f, 10.0f)].CGPath;

}

// Checks if the given touch location was on the slider. Returns YES if it was and NO if it was not.
-(BOOL) checkSliderTouchAtPoint: (CGPoint) point
{
    if (CGPathContainsPoint(_slider.path , NULL, point, NO))
    {
        return YES;
    }
    else
    {
        return NO;
    }
}

// Purpose: Takes the given touch location, determines the angle (in radians) that it forms with respect the center of the screen,
//             and returns that angle on the interval [0-2pi] radians. [0-2pi] radians follows a positive counterclockwise path.
-(double) angleForTouchPoint:(CGPoint) point
{
    // We use the positive counterclockwise coordinate system in the drawing code since that's what's used traditionally
    //    outside of Apple's APIs, so multiplying the result of
    //    atan2() by -1 converts the angle from a positive clockwise unit circle to a positive counterclockwise
    //    unit circle.

    double angleInRadians = -1*atan2(point.y - (self.frame.size.height/2), point.x - self.frame.size.width/2);

    if (angleInRadians < 0) // Convert angle to 0 - 2pi radians; we want non-negative angles.
    {
        angleInRadians += M_PI*2;
    }

    return angleInRadians;
}
// points get fed into this from the UIView.
-(void) updateWithTouchAtPoint:(CGPoint) point
{
    if ([self checkSliderTouchAtPoint:point])
    {
        double touchAngle = [self angleForTouchPoint:point];
        _slider.transform = CATransform3DMakeRotation(-M_PI, 0.0, 0.0, 1.0); // Hardcoded angle rotation for now since I need to do some subtraction later in order to determine the amount to rotate based on touches.
    }
}

我真的很感激你能提供的任何帮助!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-07-17 12:32:05

我通常认为,事件位置是用传递给的UIView来表示的。由于在_slider上有一个关于它的上层(即UIView的支持层)的转换,您想要使用的任何几何值都需要转换成那个参照系。简而言之,您需要显式地将这一点转换为_slider的参考框架。

代码语言:javascript
复制
-(BOOL) checkSliderTouchAtPoint: (CGPoint) point
{
    CGPoint pointInSliderLayer = [_slider convertPoint: point fromLayer: self.layer];
    return CGPathContainsPoint(_slider.path , NULL, pointInSliderLayer, NO);
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17679124

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档