#define centerX _currentBtn.frame.origin.x //_currentBtn 的X
#define centerY _currentBtn.frame.origin.y //_currentBtn 的Y
#define btnWHalf btnW / 2
#define adjushY 20.
#define space 10. //子btn 間距
#define margin 20. //子太援、父btn 距離
#define btnW 20.
#define btnCount 5
#define LeftCount 2
寫的有點(diǎn) 匆忙 展哭,沒有單獨(dú)封裝到UIView上,所以大家 將就 用宏代替接口吧4掀獭;馈!哈哈哈
centerY和centerX
來設(shè)置 父 按鈕 origin的x和y铃剔,
通過改變它 會改變 所有子 按鈕originx和y撒桨。btnCount
是子 按鈕的總數(shù),LeftCount
則是影響水平子按鈕左右顯示的數(shù)量键兜。
typedef void (^createPointLeft)(BOOL, NSInteger index);
typedef void (^createPointRight)(BOOL, NSInteger index);
定義兩個沒有返回值的block用來保存要重用的代碼凤类,左彈出 、右彈出
的動畫效果我們是要在水平彈出
中復(fù)用的普气。
@property (nonatomic, assign)NSTimeInterval currentTime;
用來保存每次執(zhí)行動畫前的當(dāng)前時(shí)間谜疤,以便確定每個按鈕動畫執(zhí)行的時(shí)機(jī)。
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(((0.5/(float)_btnMarr.count * (float)_btnMarr.count )) * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
_currentBtn.enabled = YES;
});
- 這段代碼為的是解決按鈕快速點(diǎn)擊现诀,導(dǎo)致動畫未執(zhí)行完成夷磕,再次生成動畫的bug。按鈕點(diǎn)下后取消點(diǎn)擊事件仔沿,延長的時(shí)間略長于動畫組執(zhí)行的時(shí)間坐桩。而后激活點(diǎn)擊事件。
self.pointLeft = ^(BOOL sure, NSInteger index){
startPoint = _currentBtn.isSelected ? CGPointMake(centerX -btnWHalf, centerY +adjushY - btnWHalf) : CGPointMake(centerX -btnWHalf - index * (btnW + space) - margin, centerY +adjushY - btnWHalf);
endPoint = _currentBtn.isSelected ? CGPointMake(centerX - btnWHalf - index * (btnW + space) - margin, centerY +adjushY - btnWHalf) : CGPointMake(centerX +btnWHalf, centerY +adjushY - btnWHalf);
};
case animationTypeShowLeft:{
self.pointLeft(YES,index);
break;
}
case animationTypeShowRight:{
self.pointRight(YES,index);
break;
}
case animationTypeShowLevel:
if (index <= LeftCount) {
self.pointLeft(YES,index);
}else{
self.pointRight(YES,index - LeftCount - 1);
}
break;
default:
break;
- 以上代碼截圖封锉,顯示的是block代碼保存區(qū)的復(fù)用绵跷。block 執(zhí)行前要給予空間。之后執(zhí)行成福,空間中的代碼碾局,并傳入?yún)?shù)。
動畫分明細(xì)
CABasicAnimation *positionAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
positionAnimation.duration=.3;
positionAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
positionAnimation.fromValue = [NSValue valueWithCGPoint:startPoint];
positionAnimation.toValue = [NSValue valueWithCGPoint:endPoint];
CAKeyframeAnimation *scaleAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
scaleAnimation.additive = YES;
scaleAnimation.values = @[@0,@(-1),@0];
scaleAnimation.keyTimes =_currentBtn.isSelected ? @[@0,@0,@1] : @[@0,@1,@1];
scaleAnimation.duration=.3;
CAAnimationGroup *animationGG = [CAAnimationGroup animation];
animationGG.duration = .3;
animationGG.repeatCount = 1;
animationGG.animations = @[positionAnimation, scaleAnimation];
animationGG.fillMode = kCAFillModeBoth;
animationGG.removedOnCompletion = YES;
animationGG.beginTime = _currentTime + (0.3/(float)_btnMarr.count * (float)i);
[btn.layer addAnimation:animationGG forKey:nil];
btn.layer.position = endPoint;
- 按鈕點(diǎn)擊位移與 縮放同時(shí)進(jìn)行奴艾。
timingFunction
意味著位移起始點(diǎn)净当、結(jié)束點(diǎn)之間運(yùn)動的時(shí)間函數(shù)。代碼中的函數(shù) 蕴潦,表示的是加速度越來越快像啼。 - 縮放 使用幀動畫 無論 彈出還是 收復(fù),我們的形變都是縮小到無回復(fù)到正常品擎。
additive
將動畫添加到mode當(dāng)前顯示層埋合,以便復(fù)用备徐。values
形變值萄传。keyTimes
每次形變值處在的時(shí)間軸。fillMode
結(jié)束的動畫樣式我們要保留。保留樣式選擇頭尾保留秀菱,這里的動畫首位不一致呢振诬。removedOnCompletion
動畫結(jié)束后刪除 渲染。防止動畫再次執(zhí)行重復(fù)的添加衍菱。-
btn.layer.position = endPoint;
改變控件 frame 赶么,保持動畫結(jié)束 后與 視圖顯示 的一致性。
-
這里強(qiáng)調(diào)一點(diǎn)position
對應(yīng)的是視圖在父視圖中錨點(diǎn)所處的位置而 我們的錨點(diǎn)默認(rèn)的是{0.5,0.5}
github源代碼
- 代碼下載地址 : btn_AnimationShow
有問題反饋
在使用中有任何問題脊串,歡迎反饋給我辫呻,可以用以下聯(lián)系方式跟我交流
- QQ: 575385842@qq.com