首页 > 代码库 > 计算Pan手势到指定点的角度

计算Pan手势到指定点的角度

计算Pan手势到指定点的角度

 

效果图:

源码:

//
//  RootViewController.m
//  Circle
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import "RootViewController.h"
#import "Radian.h"
#import "FrameAccessor.h"

@interface RootViewController ()

@property (nonatomic, strong) CALayer *layer;

@end

@implementation RootViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // 显示参考用的view
    UIView *showView = [[UIView alloc] initWithFrame:CGRectMake(0, 20, 300, 300)];
    showView.layer.borderWidth = 1.f;
    showView.layer.cornerRadius = 150.f;
    showView.layer.borderColor = [UIColor redColor].CGColor;
    showView.center = self.view.center;
    [self.view addSubview:showView];
    
    // 新建layer
    _layer = [CALayer layer];
    _layer.backgroundColor = [UIColor blackColor].CGColor;
    
    // 重置锚点
    _layer.anchorPoint = CGPointMake(0.f, 0.f);
    
    // 设置layer的frame值(在showView正中间摆放)
    _layer.frame = CGRectMake(showView.middleX, showView.middleY, 150, 1);
    
    // 添加进showView中
    [showView.layer addSublayer:_layer];
    
    // 给showView添加手势
    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
    [panGesture setMaximumNumberOfTouches:1];
    [showView addGestureRecognizer:panGesture];
}

- (void)handlePan:(UIPanGestureRecognizer *)recognizer
{
    // 获取触摸点点
    CGPoint translation = [recognizer locationInView:self.view];
    
    // 计算触摸点到中心点的弧度
    CGFloat angleInRadians = [Radian tanA:translation.y - self.view.center.y
                                        B:translation.x - self.view.center.x];
    
    // layer的动画
    [CATransaction setDisableActions:YES];
    _layer.transform = CATransform3DMakeRotation(angleInRadians, 0.0, 0.0, 1.0);
}

@end

以下3步非常关键:

引入POP库设计阻尼动画

效果如下:

//
//  RootViewController.m
//  Circle
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import "RootViewController.h"
#import "Radian.h"
#import "FrameAccessor.h"
#import "POP.h"

@interface RootViewController ()

@property (nonatomic, strong) CALayer *layer;

@end

@implementation RootViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // 显示参考用的view
    UIView *showView = [[UIView alloc] initWithFrame:CGRectMake(0, 20, 300, 300)];
    showView.layer.borderWidth = 1.f;
    showView.layer.cornerRadius = 150.f;
    showView.layer.borderColor = [UIColor redColor].CGColor;
    showView.center = self.view.center;
    [self.view addSubview:showView];
    
    // 新建layer
    _layer = [CALayer layer];
    _layer.backgroundColor = [UIColor blackColor].CGColor;
    
    // 重置锚点
    _layer.anchorPoint = CGPointMake(0.f, 0.f);
    
    // 设置layer的frame值(在showView正中间摆放)
    _layer.frame = CGRectMake(showView.middleX, showView.middleY, 150, 1);
    
    // 添加进showView中
    [showView.layer addSublayer:_layer];
    
    // 给showView添加手势
    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
    [panGesture setMaximumNumberOfTouches:1];
    [showView addGestureRecognizer:panGesture];
}

- (void)handlePan:(UIPanGestureRecognizer *)recognizer
{
    // 获取触摸点点
    CGPoint translation = [recognizer locationInView:self.view];

    // 将度数转换为弧度
#define   RADIAN(degrees)  ((M_PI * (degrees))/ 180.f)
    
    // 将弧度转换为度数
#define   DEGREES(radian)  ((radian) * 180.f / M_PI)

    
    if(recognizer.state == UIGestureRecognizerStateChanged)
    {
        // 计算触摸点到中心点的弧度
        CGFloat angleInRadians = [Radian tanA:translation.y - self.view.center.y
                                            B:translation.x - self.view.center.x];
        
        POPBasicAnimation *positionAnimation =         [POPBasicAnimation animationWithPropertyNamed:kPOPLayerRotation];
        // 设置速度动画
        positionAnimation.toValue =http://www.mamicode.com/ @(angleInRadians);
        positionAnimation.duration = 0.01f;
        
        // 添加动画
        [_layer pop_removeAnimationForKey:@"kPOPLayerRotation"];
        [_layer pop_addAnimation:positionAnimation
                          forKey:@"kPOPLayerRotation"];
    }
    
    // 拖拽动作结束
    if(recognizer.state == UIGestureRecognizerStateEnded)
    {
        // 计算触摸点到中心点的弧度
        CGFloat angleInRadians = [Radian tanA:translation.y - self.view.center.y
                                            B:translation.x - self.view.center.x];
        
        // 计算出移动的速度
        CGPoint velocity = [recognizer velocityInView:self.view];
        CGFloat x = velocity.x;
        CGFloat y = velocity.y;
        
        // 衰退减速动画
        POPDecayAnimation *positionAnimation =         [POPDecayAnimation animationWithPropertyNamed:kPOPLayerRotation];
        positionAnimation.velocity = @(+(x*ABS(cosf(angleInRadians)/100.f) +
                                         y*ABS(sinf(angleInRadians)/100.f)));
        
        // 添加动画
        [_layer pop_removeAnimationForKey:@"kPOPLayerRotation"];
        [_layer pop_addAnimation:positionAnimation
                          forKey:@"layerPositionAnimation"];
    }
}

@end

重点地方:

其实,实现这个效果真心挺难的......