QQ消除小红点(一键退朝)动画。

本来只是想写个可以拖动的小红点的,但写出乐趣来了,所以就多研究了研究,最后干脆封装了一下,可以实现给所有 View 添加黏贴效果。

GitHub 链接
效果如图:

首先需要了解贝塞尔曲线,我觉得下面这个动图,看一遍就知道贝塞尔曲线怎么回事了。

这是一个控制点(P1)的贝塞尔曲线,如果是两个控制点,则如下图

一个控制点的取了两次点,才绘制出贝塞尔曲线,所以称为二次曲线,两个控制点的取了三次点,所以称为三次曲线。

绘制贝塞尔曲线有一个数字需要记住,3.6。

三阶贝塞尔曲线拟合1/4圆

即 AB 和 CD 都垂直于 AD,AB 和 CD 的距离为 AB 距离的 1/3.6,绘制出的弧线是一个非常接近 1/4 圆的弧线。

实现思路:
需要绘制黏贴效果
拖动的 View 需要盖住其它所有其它的 View
根据拖动的距离判断松手时是需要爆炸动画还是回弹动画。

效果如下

转换成模型图如下

小圆是小红点一开始的位置,大的圆是小红点拖过去的位置,小圆随着拖动距离增大而变大,两个圆的连接其实就是两贝塞尔曲线,临时点 point_temp 根据两个圆距离的增加从 p2 向 p4 移动,连接临时点和 P1 连线中点 P5 就是控制点了,即可绘制出这条贝塞尔曲线,p3 和 p5 之间的贝塞尔曲线同理。
接下来就是计算各个点的坐标了,捡起高中的数学,还是很简单的。得出各个点的坐标,然后绘制一个大圆一个小圆,中间绘制两条贝塞尔曲线,给上填充颜色。黏贴效果就出来了。每次拖动 View 的时候再重新绘制一遍。

需要让拖动的 View 覆盖在所有 View 上方,这个还是很重要的,要不然在 tableViewCell 里进行拖动的时候,会被其它的 Cell 盖住,我的实现方式是声明一个全屏大小的 RedDotView 添加到 [[[UIApplication sharedApplication].delegate window] 上,然后将拖动的 View 拷贝一份,放置到 RedDotView 上方,隐藏旧 View。这样拖动的 View 就能盖住所有其它的 View ,包括导航栏。

拷贝我取了个巧,直接将旧 View 绘制成一张 image,放置到新 View 上显示,

- (UIImage *)getImageFromView:(UIView *)view {
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, UIScreen.mainScreen.scale);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

爆炸效果则是给 imageView 的 animationImages 属性添加六张图片,在超出最大距离之后播放。

    NSMutableArray *array = [[NSMutableArray alloc] init];
    for (int i = 1; i < 6; i++) {
        UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"red_dot_image_%d", i]];
        [array addObject:image];
    }
    UIImageView *imageView = [[UIImageView alloc] init];
    imageView.frame = CGRectMake(0, 0, radius*2, radius*2);
    imageView.center = explosionPoint;
    imageView.animationImages = array;
    [imageView setAnimationDuration:0.25];
    [imageView setAnimationRepeatCount:1];
    [imageView startAnimating];
    [self addSubview:imageView];

回弹效果是给 View 一个弹簧动画,让 View 弹回旧 View 中心的位置

    [UIView animateWithDuration:0.5 delay:0.0 usingSpringWithDamping:0.2 initialSpringVelocity:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
        view.center = point;
    } completion:^(BOOL finished) {
        ......
    }];

总结:还是有些遗憾,做完之后才注意到 QQ 的实现上,p1 和 p3 连线并不经过圆心,所以效果和 QQ 的还是有些差别,另外为了让中间的贝塞尔曲线不会和大圆重合,中间的贝塞尔曲线我用的是两条贝塞尔曲线实现,这样更圆滑一些,但也留了个坑,中间的弧度还是得再调整一下。

参考资料:
QQ手机版 5.0“一键下班”设计小结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值