-2

What I've got working:

I have been trying to add an arrow to an app, but am having the a most difficult time getting it to do what it needs to do. The arrow needs to be drawn from a start point as represented by a finger touch and increase in size while the user drags a finger across the screen. The arrow then must stop drawing one the finger is lifted.

What I'm having trouble with:

The arrow must be able to rotate around both the start point and the end point when the user touches a point a either end of the arrow and drags a finger in a direction. While rotating, the arrow must be able to increase and decrease it's size.

I am able to get the arrow to somewhat rotate around the start point, but with issues. Rotating around the end point causes a "fish tailing" effect. I'm pretty sure the way I'm doing it is completely wrong, but I don't know of any other way. This is why asking the community to steer me in the right direction.

@implementation ViewController {
ArrowView *_selectedArrowView;
UIColor *_selectedColor;
CGFloat _selectedWeight;
CGFloat _initalAngle;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    _selectedColor = [UIColor yellowColor];
    _selectedWeight = 3;

    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panHandler:)];
    [self.view addGestureRecognizer:pan];

    _selectedArrowView = [[ArrowView alloc] initWithFrame:CGRectMake(300, 300, 150, 25) withColor:_selectedColor withWeight:_selectedWeight withStartPoint:CGPointMake(300, 300) withEndPoint:CGPointMake(450, 300)];
    _selectedArrowView.delegate = self;
    _selectedArrowView.layer.anchorPoint = CGPointMake(0, 0);
    _selectedArrowView.layer.position = CGPointMake(150,300);
    [self.view addSubview:_selectedArrowView];
    [self.view bringSubviewToFront:_selectedArrowView];
}

- (void) panHandler: (UIPanGestureRecognizer *) sender {
    CGPoint touchPoint = [sender locationInView:sender.view];

    if (sender.state == UIGestureRecognizerStateBegan) {
        _initalAngle = atan2(touchPoint.y, touchPoint.x);
    } else if (sender.state == UIGestureRecognizerStateChanged) {
        CGFloat currentAngle = atan2(touchPoint.y, touchPoint.x);
        CGFloat angle = _initalAngle - currentAngle;
        CGAffineTransform transform = CGAffineTransformMakeRotation(angle * -1);
        _selectedArrowView.transform = transform;
    }
}

@end

Link to code on GitHub

4

1 回答 1

0

我认为您实际遇到的问题的核心是(来自您的评论):

如果用户选择一端并在屏幕上移动他的手指,则箭头应围绕用户触摸的另一端旋转并调整箭头的长度。

让我们假设箭头实际上是一个在自身内部绘制箭头的视图。所以这实际上是关于拉伸和旋转视图。现在让我们处理旋转部分。显然,这将通过应用“跟随”用户触摸的旋转变换来实现。这里要理解的是,一个视图实际上是一个图层,一个图层围绕它的anchorPoint.

因此,当用户第一次触摸视图时,您必须查看触摸在视图中的位置,并确定这是哪一端。然后您必须将 移动anchorPoint另一端,这样当我们随后旋转时,您将围绕另一端旋转。但是,anchorPoint除非您还更改图层以进行补偿,否则更改将导致视图跳转position,因此您也将这样做。

我们现在已经安全地将 移到anchorPoint了用户手指对面的一端。现在我们只需要在手势继续时围绕它旋转以跟随用户的手指。您将通过将触摸坐标从笛卡尔坐标转换为极坐标来完成此操作,从而给出要应用的角度。在手势开始时,保存初始角度;随着手势的继续,从当前角度中减去它,并transform使用产生的差异角度将 设置为旋转变换。

它通常有助于简化问题。在这个例子中,我没有跟随手指 - 只是制作动画。如您所见,我可以轻松地绕箭头的一端旋转,然后绕另一端旋转,然后再绕第一端旋转,以此类推。这实际上显示了在应用旋转变换之前移动 theanchorPoint和before 的效果。position我建议您先解决问题的这个简单方面,然后再担心跟随用户的手指。

在此处输入图像描述

于 2015-09-10T00:16:34.583 回答