
根據動畫效果需要分析動畫的實現就兩個重點,一個是下落,一個是彈跳,查看完整代碼和效果請 下載相關DEMO,DEMO對相關代碼進行了一定整理,現將部分關鍵代碼列出:
一、下落過程-關鍵幀動畫
- (void)pointsAnimaton
{
for (UIImageView *imageView in _itemsArray) {
CGRect frontRect = imageView.frame;
CGRect currentRect = [self realityCurrentRect];
CGFloat cX = 0;
CGFloat cY = 0;
_useDeviationValue = _deviationValue + arc4random() % 5 * 3;//偏移基礎上添加隨機值
CGFloat distance = (currentRect.origin.x + currentRect.size.width / 2.0 + _useDeviationValue) - (frontRect.origin.x + frontRect.size.width / 2.0);
cX += frontRect.origin.x + frontRect.size.width / 2.0 + distance * 0.3;
cY = frontRect.origin.y - 150;
CAKeyframeAnimation *bounceAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];//關鍵幀動畫
CGMutablePathRef thePath = CGPathCreateMutable();
bounceAnimation.delegate = self;
CGPathMoveToPoint(thePath, NULL, frontRect.origin.x + frontRect.size.width / 2.0, imageView.center.y);
//出界判斷
CGFloat toX = currentRect.origin.x + currentRect.size.width / 2.0 + _useDeviationValue;
if (toX > currentRect.origin.x + currentRect.size.width) {
toX = currentRect.origin.x + currentRect.size.width;
}
if (toX < currentRect.origin.x) {
toX = currentRect.origin.x;
}
CGPathAddQuadCurveToPoint(thePath, NULL, cX, cY, toX, currentRect.origin.y);
bounceAnimation.path = thePath;
bounceAnimation.duration = .6 + ((arc4random() % 3) * 0.04);//動畫時間(添加隨機性)
bounceAnimation.fillMode = kCAFillModeForwards;//與removedOnCompletion = NO 共同作用,動畫停留在結束位置
bounceAnimation.removedOnCompletion = NO;//與fillMode = kCAFillModeForwards 共同作用,動畫停留在結束位置
[imageView.layer addAnimation:bounceAnimation forKey:@"move"];
}
}二、到達落點後的彈跳效果-力學行為
- (void)addBehaviour
{
if (!_animator) {//力學行為容器
_animator = [[UIDynamicAnimator alloc] initWithReferenceView:_referenceView];
_animator.delegate = self;
}else{
[_animator removeAllBehaviors];
}
//重力行為
if (!_gravity) {
_gravity = [[UIGravityBehavior alloc] initWithItems:_itemsArray];
}
[_animator addBehavior:_gravity];
CGRect currentRect = [self realityBehaviourCurrentRect];//CGRectFromString(_framesArray[_currentIndex]);
//碰撞行為
if (!_collision) {
_collision = [[UICollisionBehavior alloc]
initWithItems:_itemsArray];
_collision.translatesReferenceBoundsIntoBoundary = NO;//是否與referenceView邊界碰撞
_collision.collisionDelegate = self;
}
[_collision addBoundaryWithIdentifier:@"barrier" fromPoint:currentRect.origin
toPoint:CGPointMake(currentRect.origin.x + currentRect.size.width, currentRect.origin.y)];
[_animator addBehavior:_collision];
if (!_itemBehaviour) {//行為限制
_itemBehaviour = [[UIDynamicItemBehavior alloc] initWithItems:_itemsArray];
_itemBehaviour.allowsRotation = NO;//是否允許旋轉
_itemBehaviour.elasticity = 0.6;//彈力系數(0.0 ~ 1.0)
_itemBehaviour.friction = 0.5;//摩擦系數(0.0 ~ 1.0)
}
[_animator addBehavior:_itemBehaviour];
_needPush = YES;
}