今天跨年,就在跨年中写篇博客吧。因为从上海转战广州,在广州认识的人太少,所以即使是跨年也没什么事,所以暂时只和技术为伴。先看一下动画效果,源代码链接:https://github.com/ZhengYaWei1992/QQStickAnimation
qq黏性动画以上这种效果可能在消息提示的时候会使用到,如即时通讯的消息提示按钮或者用于代替主界面的badgeValue。
先剖析一下这个动画的结构,表面上看起来主要部分是一个带有数字的红色控件模块,外加一个爆炸的动画(说明:爆炸的实际上是想做成动画效果的,无奈找不到合适的素材,所以用💥代替)。实际上红色的部分主要是由三部分组成,分别为:带有数字的按钮UIButton、由一个路径转换而成的CAShapeLayer形变效果、形变效果图的尾端的另一个红色的圆形UIView。这里要注意,形变效果的另一末尾端是一个红色的圆形UIView,只是有一半和形变图形重叠。随着圆形UIButton拖动距离增加,红色的圆形UIView的半径组件变小,当距离超过一个特定范围的时候,红色的圆形UIView以及形变的CAShapeLayer会消失。最后松开手指的时候会出现爆炸💥的动画。
再说下这种动画所用到的技术。
一、毫无疑问首先会用到拖动手势,很多拖动逻辑的都是在UIPanGestureRecognizer的手势事件中进行判断的。
二、运用数学中的股股定理计算重要的点坐标。然后通过UIBezierPath绘制填充路径。下面会详细讲解如何计算重要点的坐标值。
三、CAShapeLayer的应用,主要是把路径转换成图形,也就是效果图中的形变效果。其实核心代码也就只是一句。
具体实现:
1、 首先创建一个继承于UIButton的类(圆形带数字的红色UIButton),然后通过重载将父视图的View传过来。
- (instancetype)initWithFrame:(CGRect)frame withSuperView:(UIView *)badgeSuperView{
if (self == [super initWithFrame:frame]) {
self.bageValueSuperView = badgeSuperView;
[self setup];
}
return self;
}
2、设置圆形带数字的红色UIButton的相关属性,然后为这个按钮添加上UIPanGestureRecognizer拖动手势。另外还要创建形变效果图的尾端的另一个红色的圆形UIView对象以及相关属性。这一步实际就是上面的[self setup];方法的实现。
3、接下来看一下拖动手势中的代码。相关注释在代码中
- (void)pan:(UIPanGestureRecognizer *)pan{
CGPoint tranP = [pan translationInView:self];
CGPoint center = self.center;
center.x += tranP.x;
center.y += tranP.y;
self.center = center;
[pan setTranslation:CGPointZero inView:self];
//这个方法主要是计算圆形UIButton和圆形UIView的中心点之间的距离
CGFloat distance = [self distanceWithSmallCicle:self.smallCircle bigCircle:self];
//这里设置小圆半径随着距离拉大而缩小
CGFloat radius = self.bounds.size.width * 0.5;
radius -= distance/10.0;
self.smallCircle.bounds = CGRectMake(0, 0, radius * 2, radius * 2);
self.smallCircle.layer.cornerRadius = radius;
/*******************路径转为形状******************************/
if (self.smallCircle.hidden == NO) {
//这里是计算形变路径关键的六个点,然后返回一个路径的方法,具体计算下面会有图解。把路径转换成图形shapeLayer可以根据路径生成形状。shapeLayer是CAShapeLayer的实例对象。
UIBezierPath *path = [self pathWithSmallCircle:self.smallCircle bigCircle:self];
self.shapeLayer.path = path.CGPath;
[self.bageValueSuperView.layer insertSublayer:_shapeLayer atIndex:0];
}
/**********************关键业务逻辑处理*****************************/
//拖动距离大于60的话就隐藏形变路径和红色UIView
if (distance > 60) {
self.smallCircle.hidden = YES;
[self.shapeLayer removeFromSuperlayer];
}
//拖动结束,距离大于60就隐藏所有控件,展示爆炸动画。小于60就展示原本的状态
if (pan.state == UIGestureRecognizerStateEnded) {
if (distance < 60) {
self.center = self.smallCircle.center;
self.smallCircle.hidden = NO;
[self.shapeLayer removeFromSuperlayer];
}else{
//播放一个动画,动画执行完毕,移除所有控件。
//动画代码这里省略,具体可以下载源代码。源代码下载链接在最上方
}
}
}
4.这里就主要来剖析一下,形变区域的相关计算问题。
形变区域图解绘制红色形变区域关键的一步是计算出图中A、B、C、D、O、P四个点的位置,其中O和P点分别为AD何BC曲线的控制点。计算出六个点的位置后,便可通过贝塞尔曲线连接六个点,最后关闭路径、添加填充,便可形成一个封闭图形。六个点的具体计算是通过勾股定理计算,计算六个点的坐标,图中的辅助线很重要。根据辅助线我们不难发现凡是图中标记为Θ的角度,他们的值都相等。通过两个圆的圆心位置,不难计算出Θ值。根据Θ值以及圆心位置,便可轻而易举的计算出A、B、C、D四个点的值。另外还需要注意的是,OP的连线垂直于两个圆心所在的直线,且OA和BP的长度为两个圆心距离的一半,进而根据OA和BP外加图中的虚线辅助线,可分别计算出O点和P点圆心所在的位置。最后便可形成一个封闭区域。说了这么多,接下来可以下载一下源代码研究下。链接见上方😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀v😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀😀新年快乐!!!!!
网友评论