這個gif展現出來的效果跟真機或者模擬器顯示的仍是有差別的,在模擬器和真機上運行動畫很流暢(LICEcap最近出了問題因此沒用,湊合使用了QQ上的錄屏功能)git
有點擊事件,有圖片有數字,有狀態,UIButton最好github
1.粒子動畫的粒子生成,以後擴散,到達必定位置後消失 (粒子動畫) 2.上邊+1數字,漸變出現,達到必定y值時隱藏 (UIView動畫或幀動畫) 3.右邊的點贊數字,由0隱藏,透明度漸變出現,變爲紅色 (UIView動畫或幀動畫) 4.按鈕由灰變紅就不用說了,設置按鈕圖片就好bash
連續點擊可能出現的網絡請求問題( 點贊/取消點贊操做網絡延遲問題 )服務器
//1.建立一個能放射粒子的cell(粒子源)
CAEmitterCell * explosionCell = [CAEmitterCell emitterCell];
//透明度變化速度
explosionCell.alphaSpeed = -1.0;
//透明度變化範圍
explosionCell.alphaRange = 0.5;
//粒子存在時間
explosionCell.lifetime = 0.5;
//粒子存在時間的範圍
explosionCell.lifetimeRange = 0.2;
//每一個cell能夠釋放多少個粒子
explosionCell.birthRate = 15;
//粒子擴散的速度
explosionCell.velocity = 75.f;
//粒子擴散的速度上下區間 +10 or -10
// explosionCell.velocityRange = 10.f;
//最大 - M_PI_4/2 粒子發射方向
explosionCell.emissionLongitude = - M_PI_2;
explosionCell.emissionRange = M_PI_2;
//粒子形變大小
explosionCell.scale = 0.08;
//形變範圍
// explosionCell.scaleRange = 0.02;
//粒子內容
explosionCell.contents = (id)[[UIImage imageNamed:@"spark_red"] CGImage];
//粒子初始顏色
// explosionCell.color = [UIColor yellowColor].CGColor;
explosionCell.color = [UIColor redColor].CGColor;
//粒子其餘混合顏色
explosionCell.redRange = 10;
explosionCell.greenRange = 10;
explosionCell.blueRange = 10;
//混合色顏色變化速度
explosionCell.redSpeed = 10;
explosionCell.greenSpeed = 10;
explosionCell.blueSpeed = 10;
// 2.發射源
CAEmitterLayer * explosionLayer = [CAEmitterLayer layer];
[self.layer addSublayer:explosionLayer];
self.explosionLayer = explosionLayer;
//發射位置 - 粒子從哪裏出現開始擴散
//self.explosionLayer.emitterSize = CGSizeMake(self.bounds.size.width + 3, self.bounds.size.height + 3);
//發射源的形狀
explosionLayer.emitterShape = kCAEmitterLayerPoint;
//每秒發射cell的數量
explosionLayer.birthRate = 0;
//發射模式: 從發射體的哪一個位置發出粒子: 某個點,表面,邊緣,內部
explosionLayer.emitterMode = kCAEmitterLayerVolume;
//粒子的渲染模式
explosionLayer.renderMode = kCAEmitterLayerAdditive;
explosionLayer.emitterCells = @[explosionCell];
複製代碼
1.粒子動畫的核心就是這些代碼了,建立釋放粒子的粒子源cell,由發射源發射這些粒子源cell,這些cell擴散出粒子,造成粒子動畫網絡
2.在建立粒子源cell後設置的屬性,有的是關於粒子源自己,有的是關於擴散出來的粒子,其中帶有Range的屬性,這個是上下浮動的範圍值,即區間,例如粒子的生命週期lifetime = 0.5,設置lifetimeRange = 0.2,那麼粒子真正的生命週期是0.3 ~ 0.7,即粒子真正的生命週期是0.3 ~ 0.7的隨機值,隨機值的屬性多了,就造成了無規則的動畫ide
- emissionLongitude = - M_PI_2 表明垂直向上的方向
拳頭的放大效果用幀動畫實現,animation.keyPath = @"transform.scale"動畫
/**
* 拳頭放大動畫
*/
- (void)enlargementAnimation {
//經過鍵幀動畫實現縮放
CAKeyframeAnimation * animation = [CAKeyframeAnimation animation];
animation.keyPath = @"transform.scale";
animation.values = @[@1.5,@2.0,@3.5];
animation.duration = 0.25;
animation.calculationMode = kCAAnimationCubic;
self.backImageView.alpha = 0.05;
[self.backImageView.layer addAnimation:animation forKey:nil];
}
複製代碼
- (void)countAnimation {
//1.添加數字+1透明度動畫
CAKeyframeAnimation *animation0 = [CAKeyframeAnimation animation];
animation0.keyPath = @"opacity";
animation0.values = @[@0.5,@0.8,@1.0];
animation0.duration = 0.5;
animation0.calculationMode = kCAAnimationCubic;
[self.incLabel.layer addAnimation:animation0 forKey:nil];
//開始動畫時"+1"上升label回到起始位置
self.incLabel.y = _incOrginY;
//防止label閃爍
self.incLabel.alpha = 1;
//2.添加"+1"慢慢變大動畫
CAKeyframeAnimation *animationScale = [CAKeyframeAnimation animation];
animationScale.keyPath = @"transform.scale";
animationScale.values = @[@1.0,@1.1,@1.2];
animationScale.duration = 1.0;
animationScale.calculationMode = kCAAnimationCubic;
[self.incLabel.layer addAnimation:animationScale forKey:nil];
//3.添加"+1"s向上位移動畫
__weak typeof(self) weakSelf = self;
[UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
weakSelf.incLabel.y = self->_incOrginY - 18;
} completion:^(BOOL finished) {
//4.添加"+1"慢慢消失動畫
CAKeyframeAnimation *animation2 = [CAKeyframeAnimation animation];
animation2.keyPath = @"opacity";
animation2.values = @[@0.8,@0.5,@0];
animation2.duration = 0.5;
animation2.calculationMode = kCAAnimationCubic;
[weakSelf.incLabel.layer addAnimation:animation2 forKey:nil];
self.incLabel.alpha = 0;
}];
}
複製代碼
#import "RBCLikeButton.h"
//1.建立點贊按鈕
RBCLikeButton *likeBtn = [[RBCLikeButton alloc] initWithFrame:CGRectMake(130, 200, 100, 100)];
[likeBtn setImage:[UIImage imageNamed:@"day_like"] forState:UIControlStateNormal];
[likeBtn setImage:[UIImage imageNamed:@"day_like_red"] forState:UIControlStateSelected];
[likeBtn addTarget:self action:@selector(likeBtnClickAction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:likeBtn];
複製代碼
//點贊/取消點贊操做
- (void)likeBtnClickAction:(RBCLikeButton *)btn {
//1.記錄是不是點贊操做
BOOL isThump = !btn.isSelected;
//2.點贊量,正式運用中可自定義(從服務器獲取當前的點贊量)
NSInteger num = btn.thumpNum;
//3.計算點贊後數值
if (isThump) {
num = num + 1;//點贊後的點贊數
}else{
num = num - 1;//取消點贊後的點贊數
}
//4.調用點贊動畫,設置點贊button的點贊數值
[btn setThumbWithSelected:isThump thumbNum:num animation:YES];
//5.網絡請求
if (isThump) {//若是是點贊操做
//發起網絡請求,告知服務器APP進行了點贊操做,服務器的返回結果爲isRequestSuccess
BOOL isRequestSuccess = YES;//請求成功
if (!isRequestSuccess) {//若是操做失敗(沒有網絡或接口異常)
//取消剛纔的點贊操做致使的數值變換和點贊按鈕的狀態變化
[btn cancelLike];
}
}else{//若是是取消點贊操做
//發起網絡請求,告知服務器APP進行了取消點贊操做,服務器的返回結果爲isRequestSuccess
BOOL isRequestSuccess = NO;//請求失敗
if (!isRequestSuccess) {//若是操做失敗(沒有網絡或接口異常)
//恢復到點贊以前的點贊數值和點贊按鈕的狀態變化
[btn recoverLike];
}
}
}
複製代碼
爲何先改變本地按鈕的狀態,而後再網絡請求呢?ui
- 之因此這麼作是爲了用戶體驗考慮,直觀的展示給他操做的結果,不讓他發覺感受不到的網絡請求(由於可能存在網絡延遲的狀況)
- 咱們也準備了網絡請求失敗的補救方法recoverLike和cancelLike,這樣就能夠作好防備了
其實點贊Action的代碼仍是不夠完善 spa
由於在實操過程當中會出現用戶反覆狂擊點贊按鈕的操做,而網絡請求又是有延遲的,這樣就可能出現兩次點贊請求同時發送給了服務器,儘管有些服務器會作限制,可是你本地的代碼邏輯將會混亂,形成點贊數顯示錯誤的問題code
解決辦法:定義點贊按鈕的狀態
typedef enum : NSUInteger {
RBCLikeButtonStatusHadThumbs, //已點贊
RBCLikeButtonStatusNoneThumbs, //未點贊
RBCLikeButtonStatusThumbsing, //正在點贊
RBCLikeButtonStatusCancelThumbsing //正在取消點贊
} RBCLikeButtonStatus;
複製代碼
定義status爲點贊按鈕的點贊狀態
//若是status不是"正在取消點贊"和"正在點贊"和"已點贊"的狀態時,再執行點贊網絡請求
if ( status != RBCLikeButtonStatusCancelThumbsing
&& status != RBCLikeButtonStatusThumbsing
&& status != RBCLikeButtonStatusHadThumbs )
{
//改變本地點贊按鈕model的點贊狀態 --> 正在點贊
status = RBCLikeButtonStatusThumbsing;
//執行點讚的網絡請求
}
複製代碼
//若是status不是"正在取消點贊"和"正在點贊"和"未點贊"的狀態時,再執行取消點贊網絡請求
if ( status != RBCLikeButtonStatusCancelThumbsing
&& status != RBCLikeButtonStatusThumbsing
&& status != RBCLikeButtonStatusNoneThumbs )
{
//改變本地點贊按鈕model的點贊狀態 -->正在取消點贊
status = RBCLikeButtonStatusCancelThumbsing;
//執行取消點讚的網絡請求
}
複製代碼
1.有朋友能有更好的思路的話能夠與做者交流,有誤的地方歡迎指正
2.Demo地址: github.com/TynnPassBy/…