zoukankan      html  css  js  c++  java
  • 计算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 = @(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

    重点地方:

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

  • 相关阅读:
    URLProtocol服务协议
    ODBC、OLEDB和ADO之间的关系 ,以及性能比较
    如何在VS2015查看C#界面窗体里的控件层次
    SpeechVoiceSpeakFlags枚举类型的详细解释
    SQL中遇到多条相同内容只取一条的最简单实现方法
    flink elasticsearch sink table 忽略部分字段开发
    flink elasticsearch source table 集成elasticsearch-hadoop connector开发
    记一次python 协程给合多线程死锁问题
    kubernetes gitlab runner java maven ci/cd 整体方案示例
    某云elasticsearch节点失效,手动重置primary,迁移分区
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/3782207.html
Copyright © 2011-2022 走看看