根据动画效果需要分析动画的实现就两个重点,一个是下落,一个是弹跳,查看完整代码和效果请 下载相关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; }