需求:

點(diǎn)擊商品列表中正在售賣的商品,通過坐標(biāo)轉(zhuǎn)換和動(dòng)畫的方式,完成類似點(diǎn)贊動(dòng)畫、加入購物車、查看頭像大圖等效果。
思路及問題點(diǎn):
1)點(diǎn)擊cell中的的添加+或者減號(hào)-來完成加入購物車的動(dòng)畫事件,需要清楚用戶點(diǎn)擊的是哪一個(gè)cell上面的button,更新購物車數(shù)量等操作。
__weak typeof(self) this = self;
cell.addGoodBlock = ^(ShopListGoodsCell *cell) {
[this goodAddOrMinusAction:YES cell:cell];
[cell updateCount];
};
cell.minusGoodBlock = ^(ShopListGoodsCell *cell) {
[this goodAddOrMinusAction:NO cell:cell];
[cell updateCount];
};
2)坐標(biāo)系的轉(zhuǎn)換
將像素point由point所在視圖轉(zhuǎn)換到目標(biāo)視圖view中,返回在目標(biāo)視圖view中的像素值
這里我們要將一個(gè)位置坐標(biāo)傳出去,但是傳什么位置呢?如果是Lable的位置簡單的傳出去,那么很明顯會(huì)出現(xiàn)一個(gè)問題:不管你點(diǎn)擊那個(gè)cell的按鈕,動(dòng)畫都是從同一個(gè)起點(diǎn)出發(fā)的,而且絕對(duì)不會(huì)是任何正確的起點(diǎn)。因?yàn)槊總€(gè)cell中Label的位置都是一樣的,而我們實(shí)際需要的是這個(gè)坐標(biāo)相對(duì)于TableView的位置,也就是說它在父視圖中的位置,所以這里要將該點(diǎn)坐標(biāo)轉(zhuǎn)換。
右下角有一組圖片和按鈕,表示購物車,在tableView中有我們之前傳過來的坐標(biāo),而我們希望讓動(dòng)畫發(fā)生在view層級(jí)上,所以這里需要兩次坐標(biāo)轉(zhuǎn)換,把右下角的控件集合中的按鈕坐標(biāo)(購物車是個(gè)按鈕)和tableView中的傳過來的起點(diǎn)坐標(biāo)都轉(zhuǎn)換到self.view中,具體做法是:
if (cell) {
CGRect startRect = [cell convertRect:cell.countLab.frame toView:self.navigationController.view];
[self joinCartAnimationWithRect:startRect];
} else {
CGRect startRect = [self.goodDesView convertRect:self.countLab.frame toView:self.navigationController.view];
[self joinCartAnimationWithRect:startRect];
}
[self updateCount];
3)Bezier曲線的應(yīng)用
因?yàn)槲覀兿氘a(chǎn)生一種類拋物線的動(dòng)畫,所以這里我們需要二階Bezier曲線即可,所以要提供三個(gè)控制點(diǎn),起始點(diǎn)和終止點(diǎn)都已經(jīng)有了,關(guān)鍵就是中間的控制點(diǎn)。在計(jì)圖實(shí)驗(yàn)中生成Bezier時(shí),我們用的一種思路是以直代曲,用大量短線段來表示一條曲線,每一個(gè)n階Bezier曲線(n+1個(gè)點(diǎn))在生成時(shí),總能在n個(gè)線段中按照一個(gè)比例各找出一個(gè)點(diǎn),而這n個(gè)點(diǎn)又能生成一個(gè)n-1階Bezier,我們的Bezier曲線上的點(diǎn)就是當(dāng)只有一條線段以后按照那個(gè)比例找出的那個(gè)點(diǎn)。
UIView的動(dòng)畫是作用在layer層級(jí)的,所以我們可以生成一個(gè)CALayer,在這個(gè)layer上添加上自己的圖片,然后將動(dòng)畫應(yīng)用到這個(gè)layer中即可。
#pragma mark -加入購物車動(dòng)畫
-(void) joinCartAnimationWithRect:(CGRect)rect
{
//加入購物車結(jié)束點(diǎn)
CGFloat endPoint_x = 35;
CGFloat endPoint_y = SCREEN_HEIGHT - 35;
//加入購物車開始點(diǎn)
CGFloat startX = rect.origin.x;
CGFloat startY = rect.origin.y;// 和頭部差值
//繪制貝塞爾曲線
UIBezierPath *path= [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(startX, startY)];
//三點(diǎn)曲線 讓動(dòng)畫下滑的路線
[path addCurveToPoint:CGPointMake(endPoint_x, endPoint_y)
controlPoint1:CGPointMake(startX, startY)
controlPoint2:CGPointMake(startX - 180, startY - 200)];
CALayer *dotLayer = [CALayer layer];
dotLayer.backgroundColor = [UIColor colorWithRed:244.0/255.0 green:80.0/255.0 blue:100.0/255.0 alpha:1].CGColor;
dotLayer.frame = CGRectMake(0, 0, 16, 16);
dotLayer.cornerRadius = 8;
[self.view.layer addSublayer:dotLayer];
[self groupAnimation:path.CGPath layer:dotLayer];
}
#pragma mark - 組合動(dòng)畫
-(void)groupAnimation:(CGPathRef)path layer:(CALayer*)layer;
{
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
animation.path = path;
animation.rotationMode = kCAAnimationRotateAuto;
CABasicAnimation *alphaAnimation = [CABasicAnimation animationWithKeyPath:@"alpha"];
alphaAnimation.duration = 0.2f;
alphaAnimation.fromValue = [NSNumber numberWithFloat:1.0];
alphaAnimation.toValue = [NSNumber numberWithFloat:0.1];
alphaAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
CAAnimationGroup *groups = [CAAnimationGroup animation];
groups.animations = @[animation,alphaAnimation];
groups.duration = 0.5f;
groups.removedOnCompletion = NO;
groups.fillMode = kCAFillModeForwards;
groups.delegate = self;
[groups setValue:@"groupsAnimation" forKey:@"animationName"];
[layer addAnimation:groups forKey:nil];
[self performSelector:@selector(removeFromLayer:) withObject:layer afterDelay:0.5f];
}
- (void)removeFromLayer:(CALayer *)layerAnimation{
[layerAnimation removeFromSuperlayer];
}
#pragma mark - CAAnimationDelegate
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
//[self performSelector:@selector(removeFromLayer:) withObject:dotLayer afterDelay:0.8f];
if ([[anim valueForKey:@"animationName"]isEqualToString:@"groupsAnimation"]) {
CABasicAnimation *shakeAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
shakeAnimation.duration = 0.25f;
shakeAnimation.fromValue = [NSNumber numberWithFloat:0.9];
shakeAnimation.toValue = [NSNumber numberWithFloat:1];
shakeAnimation.autoreverses = YES;
//這個(gè)是下方的自定義View上面放的btn
[self.cardView.cartBtn.layer addAnimation:shakeAnimation forKey:nil];
}
}