本文介绍了旋转动画,遵循手指,uibuttons的后面圆的外路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在找一些指导,开始搞清楚,跟踪手指的运动,并沿圆的外部通道

I am looking for a little guidance to start figuring out an animation that tracks finger movement and moves a collection of UIButtons along the outer path of a circle

我想象它会有种有左轮手枪的感觉。就像在底部每一个锁定到位

I am picturing it will kind of have a revolver feel to it. Like each one locks into place at the bottom

或想通过这些幻灯片插入

or like the swiping through one of the slide inserts of these

在此先感谢

推荐答案

(上样品code)

这不是真的那么难,但只是参与了很多三角的。

It's not really that difficult, there's just a lot of trigonometry involved.

现在,我现在要形容,不是一个动画,因为你要求为它来跟踪你的手指在标题位置。动画将涉及自己的计时功能,但因为你正在使用的触摸手势,我们可以利用固有的时机,本次盛会,只是相应地旋转视图。 (TL; DR:用户保持运动,而不是隐式计时器的时间)

Now, what I'm going to describe now, is not an animation, since you requested for it to track the position of your finger in the title. An animation would involve its own timing function, but since you're using the touch gesture, we can use the inherent timing that this event has and just rotate the view accordingly. (TL;DR: The user keeps the time of the movement, not an implicit timer).

首先,让我们定义,保持角度轨道便捷类,我会叫它 DialView 。这真的只是一个UIView的子类,具有以下属性:

First of all, let's define a convenient class that keeps track of the angle, I'm gonna call it DialView. It's really just a subclass of UIView, that has the following property:

@interface DialView : UIView

@property (nonatomic,assign) CGFloat angle;

@end

DialView.m

- (void)setAngle:(CGFloat)angle
{
    _angle = angle;
    self.transform = CGAffineTransformMakeRotation(angle);
}

的UIButton s时,可以包含在此视图中(我不知道,如果你想上的按钮来负责轮换?我会使用 UIPanGestureRecognizer ,因为它是最便捷的方式)。

The UIButtons can be contained within this view (I'm not sure if you want the buttons to be responsible for the rotation? I'm gonna use a UIPanGestureRecognizer, since it's the most convenient way).

让我们构建,将手柄内平移手势视图控制器我们的 DialView ,让我们也保持DialView参考。

Let's build the view controller that will handle a pan gesture inside our DialView, let's also keep a reference to DialView.

@class DialView;

@interface ViewController : UIViewController

// The previously defined dial view
@property (nonatomic,weak) IBOutlet DialView *dial;

// UIPanGesture selector method
- (IBAction)didReceiveSpinPanGesture:(UIPanGestureRecognizer*)gesture;

@end

这是给你的,你怎么挂钩泛姿态,就个人而言,我做它的笔尖文件。现在,这个功能的主体:

It's up to you on how you hook up the pan gesture, personally, I made it on the nib file. Now, the main body of this function:

- (IBAction)didReceiveSpinPanGesture:(UIPanGestureRecognizer*)gesture
{
    // This struct encapsulates the state of the gesture
    struct state
    {
        CGPoint touch;          // Current touch position
        CGFloat angle;          // Angle of the view
        CGFloat touchAngle;     // Angle between the finger and the view
        CGPoint center;         // Center of the view
    };

    // Static variable to record the beginning state
    // (alternatively, use a @property or an _ivar)
    static struct state begin;

    CGPoint touch = [gesture locationInView:nil];

    if (gesture.state == UIGestureRecognizerStateBegan)
    {
        begin.touch  = touch;
        begin.angle  = self.dial.angle;
        begin.center = self.dial.center;

        begin.touchAngle = CGPointAngle(begin.touch, begin.center);
    }
    else if (gesture.state == UIGestureRecognizerStateChanged)
    {
        struct state now;
        now.touch   = touch;
        now.center  = begin.center;

        // Get the current angle between the finger and the center
        now.touchAngle = CGPointAngle(now.touch, now.center);

        // The angle of the view shall be the original angle of the view
        // plus or minus the difference between the two touch angles
        now.angle = begin.angle - (begin.touchAngle - now.touchAngle);

        self.dial.angle = now.angle;
    }
    else if (gesture.state == UIGestureRecognizerStateEnded)
    {
        // (To be Continued ...)
    }
}

CGPointAngle 是由我发明了一种方法,它只是为 ATAN2 一个漂亮的包装(我扔 CGPointDistance 如果您致电NOW):

CGPointAngle is a method invented by me, it's just a nice wrapper for atan2 (and I'm throwing CGPointDistance in if you call NOW!):

CGFloat CGPointAngle(CGPoint a, CGPoint b)
{
    return atan2(a.y - b.y, a.x - b.x);
}

CGFloat CGPointDistance(CGPoint a, CGPoint b)
{
    return sqrt(pow((a.x - b.x), 2) + pow((a.y - b.y), 2));
}

这里的关键是,有两个角度追踪:

The key here, is that there's two angles to keep track:


  1. 视图本身
  2. 的角度
  3. 您的手指和视图的中心之间形成的角度。

在这种情况下,我们希望有视图的角度为 originalAngle + deltaFinger ,这是上面的code做什么,我只是封装在所有的国家一个结构。

In this case, we want to have the view's angle be originalAngle + deltaFinger, and that's what the above code does, I just encapsulate all the state in a struct.

如果你想保持轨道上的观点的边界,你应该使用 CGPointDistance 方法,并检查 begin.center 和 now.finger 是一个特定的值。

If that you want to keep track on "the border of the view", you should use the CGPointDistance method and check if the distance between the begin.center and the now.finger is an specific value.

这是功课哦!

好了,现在,这一部分是一个实际的动画,因为用户不再拥有控制权。

Ok, now, this part is an actual animation, since the user no longer has control of it.

的捕捉可通过具有角度的定义的一组来实现,并且当手指释放手指(手势结束),弹回至它们,像这样:

The snapping can be achieved by having a set defined of angles, and when the finger releases the finger (Gesture ended), snap back to them, like this:

else if (gesture.state == UIGestureRecognizerStateEnded)
{
    // Number of "buttons"
    NSInteger buttons = 8;

    // Angle between buttons
    CGFloat angleDistance = M_PI*2 / buttons;

    // Get the closest angle
    CGFloat closest = round(self.dial.angle / angleDistance) * angleDistance;

    [UIView animateWithDuration:0.15 animations:^{
        self.dial.angle = closest;
    }];
}

按钮变量,只是一个替身是在视图按钮的数量。该公式是超级​​简单实际上,它只是滥用取整函数逼近的角度关闭

The buttons variable, is just a stand-in for the number of buttons that are in the view. The equation is super simple actually, it just abuses the rounding function to approximate to the closes angle.

这篇关于旋转动画,遵循手指,uibuttons的后面圆的外路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 13:03
查看更多