JHChainableAnimations源碼學(xué)習(xí)
JHChainableAnimations是什么
JHChainableAnimations 是一個(gè)多系統(tǒng)動(dòng)畫封裝的鏈?zhǔn)秸Z(yǔ)法庫(kù)。
原有的OC代碼如果我們想寫一個(gè)動(dòng)畫,需要這樣寫。
[UIView animateWithDuration:1.0
delay:0.0
usingSpringWithDamping:0.8
initialSpringVelocity:1.0
options:0 animations:^{
CGPoint newPosition = self.myView.frame.origin;
newPosition.x += 50;
self.myView.frame.origin = newPosition;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationOptionCurveEaseIn
animations:^{
self.myView.backgroundColor = [UIColor purpleColor];
} completion:nil];
}];
使用 JHChainableAnimations 可以這樣寫:
JHChainableAnimator *animator = [[JHChainableAnimator alloc] initWithView:self.myView];
animator.moveX(50).spring.thenAfter(1.0).makeBackground([UIColor purpleColor]).easeIn.animate(0.5);
代碼一下就顯得特別清晰明了,JHChainableAnimations 采用了現(xiàn)在流行的鏈?zhǔn)秸Z(yǔ)法,跟 Masonry 一樣的語(yǔ)法。
鏈?zhǔn)秸Z(yǔ)法的特點(diǎn)是什么
鏈?zhǔn)骄幊烫攸c(diǎn):方法的返回值是block,block必須有返回值(本身對(duì)象),block參數(shù)(需要操作的值)
JHChainableAnimations代碼具體分析
首先看一段代碼
JHChainableAnimator *animator = [[JHChainableAnimator alloc] initWithView:self.myView];
animator.moveX(100).animate(2);
首先是將 self.myView 與 JHChainableAnimator *animator 關(guān)聯(lián)起來,然后通過 JHChainableAnimator *animator 進(jìn)行動(dòng)畫設(shè)置。
第二行代碼
animator.moveX(100).animate(2);
首先是 animator 調(diào)用 moveX 方法生成動(dòng)畫樣式,這個(gè)方法從字面上面看 就是 移動(dòng)視圖的X軸,然后調(diào)用 animate 執(zhí)行動(dòng)畫,設(shè)置動(dòng)畫時(shí)間。具體看先 它是如何實(shí)現(xiàn)的。
- (JHChainableFloat)moveX
{
JHChainableFloat chainable = JHChainableFloat(f) {
[self addAnimationCalculationAction:^(__weak UIView *view, __weak JHChainableAnimator *weakSelf) {
JHKeyframeAnimation *positionAnimation = [weakSelf basicAnimationForKeyPath:@"position.x"];
positionAnimation.fromValue = @(view.layer.position.x);
positionAnimation.toValue = @(view.layer.position.x+f);
[weakSelf addAnimationFromCalculationBlock:positionAnimation];
}];
[self addAnimationCompletionAction:^(__weak UIView *view, __weak JHChainableAnimator *weakSelf) {
CGPoint position = view.layer.position;
position.x += f;
view.layer.position = position;
}];
return self;
};
return chainable;
}
再來回顧下鏈?zhǔn)秸Z(yǔ)法的特點(diǎn):
方法的返回值是block,block必須有返回值(本身對(duì)象),block參數(shù)(需要操作的值)
再來看上面這段代碼:
-
moveX方法返回的是一個(gè)block chainable -
block的參數(shù)是一個(gè)float, -
block chainable的返回值是當(dāng)前類JHChainableAnimator實(shí)例。
完全符合鏈?zhǔn)秸Z(yǔ)法的特點(diǎn)。
moveX 具體實(shí)現(xiàn)
然后再來看具體實(shí)現(xiàn),moveX 干了什么。
首先是返回了一個(gè) block,然后這個(gè) block 返回了這個(gè)類本身的實(shí)例。
block chainable 都做了什么
- 生成一個(gè)可執(zhí)行的動(dòng)畫
[self addAnimationCalculationAction:^(__weak UIView *view, __weak JHChainableAnimator *weakSelf) {
JHKeyframeAnimation *positionAnimation = [weakSelf basicAnimationForKeyPath:@"position.x"];
positionAnimation.fromValue = @(view.layer.position.x);
positionAnimation.toValue = @(view.layer.position.x+f);
[weakSelf addAnimationFromCalculationBlock:positionAnimation];
}];
- 生成有個(gè)動(dòng)畫執(zhí)行完畢的回調(diào),修改視圖屬性
[self addAnimationCompletionAction:^(__weak UIView *view, __weak JHChainableAnimator *weakSelf) {
CGPoint position = view.layer.position;
position.x += f;
view.layer.position = position;
}];
- 返回 當(dāng)前類本身
animate 具體實(shí)現(xiàn)
- (JHChainableAnimation)animate
{
JHChainableAnimation chainable = JHChainableAnimation(t) {
return self.animateWithCompletion(t, self.completionBlock);
};
return chainable;
}
華麗的分割線
感覺自己的語(yǔ)言表示能力有問題,突然不知道該怎么往下說下去了。
這個(gè)地方。
重新描述下:
首先是像
- (JHChainableFloat)moveX; - (JHChainableFloat)moveY; - (JHChainablePoint)moveXY; - (JHChainableFloat)moveHeight; - (JHChainableFloat)moveWidth;這類方法調(diào)用的時(shí)間,會(huì)生成一些類的動(dòng)畫對(duì)象
JHKeyframeAnimation然后存儲(chǔ)到JHAnimationChainLink的動(dòng)畫數(shù)組里面。
最終
animate方法是循環(huán)調(diào)用 類數(shù)組里面存儲(chǔ)的JHAnimationChainLink對(duì)象,執(zhí)行JHAnimationChainLink對(duì)象的JHKeyframeAnimation動(dòng)畫數(shù)組。
大致就是這樣執(zhí)行的,但是具體的實(shí)現(xiàn)有好多細(xì)節(jié),動(dòng)畫的添加,動(dòng)畫執(zhí)行的回調(diào),取得當(dāng)前執(zhí)行的動(dòng)畫、如何暫停動(dòng)畫等。感覺自己目前的功力還很難描述清楚。就暫時(shí)先告一段落了。