核心动画-QQ消息提示按钮实现

100 阅读2分钟

效果

IMG_6664.GIF

思路:

截屏2022-09-25 00.25.13.png

截屏2022-09-25 00.26.23.png

截屏2022-09-25 00.27.00.png

截屏2022-09-25 00.27.23.png

截屏2022-09-25 00.27.49.png

截屏2022-09-25 00.28.09.png

截屏2022-09-25 00.28.20.png

截屏2022-09-25 00.28.32.png

代码

#import "ViewController.h"
/*
 拆分动画:
 1.2个圆(一个固定圆,一个拖拽圆) (完成!)
 2.贝塞尔曲线,求得关键点 (完成!)
 3.固定圆的比例缩小
 4.拖拽到一定距离则需要断开
 5.断开之后有一个反弹的动画效果
 */


@interface ViewController ()
//圆1
@property (nonatomic, strong) UIView *view1;
//圆2
@property (nonatomic, strong) UIView *view2;
//shapeLayer图层
@property (nonatomic, strong) CAShapeLayer *shapeLayer;

//坐标记录
@property (nonatomic, assign) CGPoint oldViewCenter;
@property (nonatomic, assign) CGRect oldViewFrame;
@property (nonatomic, assign) CGFloat r1;


@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    //1.UI.
    [self setUp];
}

-(void)setUp
{
    //1.view1
    _view1 = [[UIView alloc]initWithFrame:CGRectMake(36, CGRectGetHeight(self.view.bounds)-66, 40, 40)];
    _view1.layer.cornerRadius = 20;
    _view1.backgroundColor = [UIColor redColor];
    [self.view addSubview:_view1];
    
    //2.view2
    _view2 = [[UIView alloc]initWithFrame:CGRectMake(36, CGRectGetHeight(self.view.bounds)-66, 40, 40)];
    _view2.layer.cornerRadius = 20;
    _view2.backgroundColor = [UIColor redColor];
    [self.view addSubview:_view2];
    
    //3.提示数
    UILabel *label = [[UILabel alloc]initWithFrame:_view2.bounds];
    label.text = @"99";
    label.textAlignment = NSTextAlignmentCenter;
    label.textColor = [UIColor whiteColor];
    [_view2 addSubview:label];
    
    
    //4.添加手势
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panAction:)];
    [_view2 addGestureRecognizer:pan];
    
    _shapeLayer = [[CAShapeLayer alloc]init];
    _oldViewFrame = _view1.frame;
    _oldViewCenter = _view1.center;
    _r1 = CGRectGetWidth(_view1.frame)/2;
    
    
}

-(void)panAction:(UIPanGestureRecognizer *)pan{
    
    if (pan.state == UIGestureRecognizerStateChanged) {
        
        //_view2.跟着你手指移动
        _view2.center = [pan locationInView:self.view];
      
        //当我们拖拽到一定距离,则移除
        if (_r1 < 9) {
            _view1.hidden = YES;
            [_shapeLayer removeFromSuperlayer];
        }
        [self caculPoint];
    }else if(pan.state == UIGestureRecognizerStateEnded || pan.state == UIGestureRecognizerStateFailed || pan.state == UIGestureRecognizerStateCancelled)
    {
        //回弹!
        //_view2.位置恢复! shaperLayer消失!
        //[_shapeLayer removeFromSuperlayer];
        //_view2.center = _oldViewCenter;
        
        [_shapeLayer removeFromSuperlayer];
        __weak typeof(self) weakSelf = self;
        [UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.3 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
            
            weakSelf.view2.center = weakSelf.oldViewCenter;
            
        } completion:^(BOOL finished) {
            
            weakSelf.view1.hidden = NO;
            weakSelf.view1.frame = weakSelf.oldViewFrame;
            weakSelf.r1 = weakSelf.oldViewFrame.size.width/2;
            weakSelf.view1.layer.cornerRadius = weakSelf.r1;
            
        }];
        
        
    }
    
}

-(void)caculPoint{
    
    //1已知条件: 圆1/2的中心点,斜边d,半径r1,r2;
    CGPoint center1 = _view1.center;
    CGPoint center2 = _view2.center;
    
    //2.斜边
    //d = sqrtf((x2-x1)•(x2-x1)+(y1-y2)•(y1-y2));
    float dis = sqrtf(pow(center2.x - center1.x, 2)+pow(center1.y - center2.y, 2));
    
    //3.正弦/余弦值.
    float sinValue = (center2.x - center1.x)/dis;
    float cosValue = (center1.y - center2.y)/dis;
    
    //4.半径
    float r1 = CGRectGetWidth(_oldViewFrame)/2 - dis/20;
    float r2 = CGRectGetWidth(_view2.frame)/2;
    _r1 = r1;
    
    //5.求ABCDOP 6个点!
    CGPoint pointA = CGPointMake(center1.x - r1*cosValue, center1.y - r1*sinValue);
    CGPoint pointB = CGPointMake(center1.x + r1*cosValue, center1.y + r1*sinValue);
    CGPoint pointC = CGPointMake(center2.x + r2*cosValue, center2.y + r1*sinValue);
    CGPoint pointD = CGPointMake(center2.x - r1*cosValue, center2.y - r2*sinValue);
    
    CGPoint pointO = CGPointMake(pointA.x+dis/2*sinValue, pointA.y-dis/2*cosValue);
    CGPoint pointP = CGPointMake(pointB.x+dis/2*sinValue, pointB.y-dis/2*cosValue);
    
    
    //6.绘制贝塞尔曲线
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:pointA];
    [path addQuadCurveToPoint:pointD controlPoint:pointO];
    [path addLineToPoint:pointC];
    [path addQuadCurveToPoint:pointB controlPoint:pointP];
    [path closePath];
    
    if (_view1.hidden) {
        return;
    }
   
    _shapeLayer.path = path.CGPath;
    _shapeLayer.fillColor = [UIColor redColor].CGColor;
    [self.view.layer insertSublayer:_shapeLayer below:_view2.layer];
    
    
    _view1.center = _oldViewCenter;
    _view1.bounds = CGRectMake(0, 0, r1*2, r1*2);
    _view1.layer.cornerRadius = r1;
    
}