根據動畫效果需要分析動畫的實現就兩個重點,一個是下落,一個是彈跳,查看完整代碼和效果請 下載相關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; }