跟随圆的外部路径的uibuttons跟随手指的旋转动画 [英] Revolving animation, that follows finger, of uibuttons that follows outer path of circle

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

问题描述

我正在寻找一些指导来开始找出一个动画来跟踪手指运动并沿着圆圈的外部路径移动一组 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

提前致谢

推荐答案

(GitHub上的示例代码)

其实并没有那么难,只是涉及到很多三角函数.

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

拨号视图.m

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

UIButton 可以包含在此视图中(我不确定您是否希望按钮负责旋转?我将使用 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

如何连接平移手势取决于您,我个人是在 nib 文件上制作的.现在,这个函数的主体:

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 扔进去现在!):

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. 手指与视图中心形成的角度.

在这种情况下,我们希望视图的角度为originalAngle + deltaFinger,这就是上面的代码所做的,我只是将所有状态封装在一个结构中.

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;
    }];
}

buttons 变量只是视图中按钮数量的替代.这个方程其实超级简单,就是滥用舍入函数逼近闭角.

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跟随手指的旋转动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆