端午节本来想出去玩耍,但是可恶的天气。好吧,在屋子里接着写代码。之后一个月就要安心复习了。
这次做的东西受到了Facebook Paper的like按钮影响,也自己做了一个来玩。其实网上早就有现成的轮子,但是个人觉得他们的封装太繁琐,所以自己按照自己的实现思路来实现了一下。
这次写的动画要简单的多。看到上面的成果图之后,很显然的就能看出分成两部分。
下面我们逐一攻克。
除去粒子爆炸效果,就是一个大拇指的缩放动画。为了让体验最佳,当我们手指按下按钮的时候,最好有一个动画的过渡来告知按钮已被按下。而在所以动画动作,最好的体现手法就是按钮的放缩,这也符合物理中力学的按压动作,使物体产生形变。
至于实现起来就很容易了,我们用 transform
属性,对目标View添加放缩动画,再按帧加载,来控制View的变换情况。帧动画在之前的 Particle Explosion Effect 有所提及,即使不看讲解直接看代码的参数名称也是一目了然的,这里直接给出代码,不再讲解:
#pragma mark - Methods - (void) clickButtonPress { if (isSelected) [self popInsideWithDuration: 0.5]; else { [self popOutsideWithDuration: 0.5]; // [self.explodeAnimationView animate]; }; } - (void) popOutsideWithDuration: (NSTimeInterval) duringTime { __weak typeof(self) weakSelf = self; self.transform = CGAffineTransformIdentity; [UIView animateKeyframesWithDuration: duringTime delay: 0 options: 0 animations: ^{ [weakSelf setImage: [UIImage imageNamed: @"Like-Blue"] forState: UIControlStateNormal]; [UIView addKeyframeWithRelativeStartTime: 0 relativeDuration: 1 / 3.0 animations: ^{ typeof(self) strongSelf = weakSelf; strongSelf.transform = CGAffineTransformMakeScale(1.5, 1.5); }]; [UIView addKeyframeWithRelativeStartTime: 1 / 3.0 relativeDuration: 1 / 3.0 animations: ^{ typeof(self) strongSelf = weakSelf; strongSelf.transform = CGAffineTransformMakeScale(0.8, 0.8); }]; [UIView addKeyframeWithRelativeStartTime: 2 / 3.0 relativeDuration: 1 / 3.0 animations: ^{ typeof(self) strongSelf = weakSelf; strongSelf.transform = CGAffineTransformMakeScale(1.0, 1.0); }]; } completion: ^(BOOL finished) { isSelected = YES; }]; } - (void) popInsideWithDuration: (NSTimeInterval) duringTime { __weak typeof(self) weakSelf = self; self.transform = CGAffineTransformIdentity; [UIView animateKeyframesWithDuration: duringTime delay: 0 options: 0 animations: ^{ [weakSelf setImage: [UIImage imageNamed: @"Like-PlaceHold"] forState: UIControlStateNormal]; [UIView addKeyframeWithRelativeStartTime: 0 relativeDuration: 1 / 2.0 animations: ^{ typeof(self) strongSelf = weakSelf; strongSelf.transform = CGAffineTransformMakeScale(0.8, 0.8); }]; [UIView addKeyframeWithRelativeStartTime: 1 / 2.0 relativeDuration: 1 / 2.0 animations: ^{ typeof(self) strongSelf = weakSelf; strongSelf.transform = CGAffineTransformMakeScale(1.0, 1.0); }]; } completion: ^(BOOL finished) { isSelected = NO; }]; }
这里的爆炸,我们不需要像之前的气泡爆炸一样,来切割View。想法是之前消息气泡的动画是为了让消息气泡有一种破裂的感觉,所以我们直接对视图进行粒子分割。而这里的粒子动画,就好像是拇指视图在经过按压之后,在墙面上敲击震动后扬起的灰尘,这些粒子不是属于原视图的。我们在多次观看最终结果图后,发现这是最合理的思路。
当我们确定思路后,我们会发现工作量减少了很多。因为我们使用 CALayer
的一个高性能原生粒子引擎来解决 CAEmitterLayer
。详细的相关属性和方法可以查看 CAEmitterLayer官方文档 。这里还是简单的介绍一下这个类,我们可以把 CAEmitterLayer
当做许多 CAEmitterCell
的容器,每一个cell也就是我们细化出的每一刻粒子。然而我们只需要定义一个 CAEmitterLayer
粒子效果来作为粒子样式模板即可, CAEmitterLayer
负责基于模板实例化该样式的粒子流,使他们同时刻以动画形式表现。
以下是初始化 CAEmitterLayer
以及 CAEmitterCell
的代码:
#pragma mark - Initial Function - (void) StartUp { self.clipsToBounds = NO; self.userInteractionEnabled = NO; CAEmitterCell *emitter = [CAEmitterCell emitterCell]; emitter.contents = (id)[UIImage imageNamed: @"Like-Sparkle"].CGImage; emitter.name = @"explosion"; emitter.alphaRange = 0.2f; emitter.alphaSpeed = -1.f; emitter.lifetime = 0.7f; emitter.lifetimeRange = 0.3f; emitter.birthRate = 0; emitter.velocity = 40.0f; emitter.velocityRange = 10.0f; emitter.emissionRange = M_PI_4; emitter.scale = 0.05f; emitter.scaleRange = 0.02; _emitterLayer = [CAEmitterLayer layer]; _emitterLayer.name = @"emitterLayer"; _emitterLayer.emitterShape = kCAEmitterLayerCircle; _emitterLayer.emitterMode = kCAEmitterLayerOutline; _emitterLayer.emitterPosition = self.center; _emitterLayer.emitterSize = CGSizeMake(25, 0); _emitterLayer.renderMode = kCAEmitterLayerOldestFirst; _emitterLayer.masksToBounds = NO; _emitterLayer.emitterCells = @[emitter]; _emitterLayer.frame = [UIScreen mainScreen].bounds; [self.layer addSublayer: _emitterLayer]; _emitterLayer.emitterPosition = self.center; }
CAMitterCell
的属性基本上可以分为3种:
emissionRange
属性的值是2π,这意味着例子可以从360度任意位置反射出来。如果指定一个小一些的值,就可以创造出一个圆锥形。 总结了以上一般性规律,我们队 CAMitterCell
的认识又进了一步。我想,你以及可以用他来制作火焰或者下雪的动效了。对吧~
以上就是简单的点赞按钮动画效果。
在制作完这个样例push到github上之后,我还配置了 CocoaPods
安装方式(这也是我第一个支持CocoaPods的开源小库,走个国际范嘛~)。有机会的话,下次我们来分享如何装载 .podspec
文件,最近要开始突击期末考试了,暂停写代码,说不定下次再分享作品就是在上海了~
Github【Desgard_Duan】