你如何创build一个类似于iphone删除animation的摆动animation

我们正在开发一个包含一系列图标的应用程序。 我们希望图标像按下应用程序删除animation时摆动。 什么是编码这个animation序列的最好方法?

Vinzius的答案是非常酷的。 但摆动只从0弧度旋转到0.08。 因此摆动看起来有点不平衡。 如果您遇到同样的问题,则可能需要使用CAKeyframeAnimation而不是CABasicRotation添加负向和正向旋转:

- (CAAnimation*)getShakeAnimation { CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"transform"]; CGFloat wobbleAngle = 0.06f; NSValue* valLeft = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(wobbleAngle, 0.0f, 0.0f, 1.0f)]; NSValue* valRight = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(-wobbleAngle, 0.0f, 0.0f, 1.0f)]; animation.values = [NSArray arrayWithObjects:valLeft, valRight, nil]; animation.autoreverses = YES; animation.duration = 0.125; animation.repeatCount = HUGE_VALF; return animation; } 

你可以使用这个animation方法来做你的视图或button。

 [self.yourbutton.layer addAnimation:[self getShakeAnimation] forKey:@""]; 

再仔细看看iOS的实现,有两件事让他们比这里提到的代码更逼真一些:

  • 图标似乎有一个反弹,以及一个旋转
  • 每个图标都有自己的时间 – 他们并不是全部同步

我基于自己的答案在这里(并从这个答案的一些帮助),以增加每个animation的持续时间的旋转,反弹和一点随机性。

 #define kWiggleBounceY 4.0f #define kWiggleBounceDuration 0.12 #define kWiggleBounceDurationVariance 0.025 #define kWiggleRotateAngle 0.06f #define kWiggleRotateDuration 0.1 #define kWiggleRotateDurationVariance 0.025 -(void)startWiggling { [UIView animateWithDuration:0 animations:^{ [self.layer addAnimation:[self rotationAnimation] forKey:@"rotation"]; [self.layer addAnimation:[self bounceAnimation] forKey:@"bounce"]; self.transform = CGAffineTransformIdentity; }]; } -(CAAnimation*)rotationAnimation { CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"]; animation.values = @[@(-kWiggleRotateAngle), @(kWiggleRotateAngle)]; animation.autoreverses = YES; animation.duration = [self randomizeInterval:kWiggleRotateDuration withVariance:kWiggleRotateDurationVariance]; animation.repeatCount = HUGE_VALF; return animation; } -(CAAnimation*)bounceAnimation { CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.y"]; animation.values = @[@(kWiggleBounceY), @(0.0)]; animation.autoreverses = YES; animation.duration = [self randomizeInterval:kWiggleBounceDuration withVariance:kWiggleBounceDurationVariance]; animation.repeatCount = HUGE_VALF; return animation; } -(NSTimeInterval)randomizeInterval:(NSTimeInterval)interval withVariance:(double)variance { double random = (arc4random_uniform(1000) - 500.0) / 500.0; return interval + variance * random; } 

我在UICollectionView上实现了这个代码,其中有30个项目弹跳,并且在iPad 2上performance完美无瑕。

我试图做一个这样的iPad应用程序的东西。

我试图做一些旋转(与CAAnimation)的观点。 这里是我写的一个示例代码:

  - (CAAnimation *)getShakeAnimation {

     CABasicAnimation *animation;
     CATransform3D转换;

     //创build旋转matrix
     transform = CATransform3DMakeRotation(0.08,0,0,1.0);

     //创build一个基本的animation来animation层的变换
     animation = [CABasicAnimation animationWithKeyPath:@“transform”];

     //将转换分配为animation的值
     animation.toValue = [NSValue valueWithCATransform3D:transform];

     animation.autoreverses = YES;  
     animation.duration = 0.1;  
     animation.repeatCount = HUGE_VALF;  

    返回animation;

 } 

你应该尝试应用这个到你的图层(使用函数:addAnimation)。 在这里,autoreverses属性是交替的左右方向。 尝试设置其他值的angular度和持续时间。

但在我的情况下,我不得不添加其他angular度的CATransform3DMakeRotation方法,取决于初始图层方向^^

祝你好运 ! 文森特

SWIFT: –

 let transformAnim = CAKeyframeAnimation(keyPath:"transform") transformAnim.values = [NSValue(CATransform3D: CATransform3DMakeRotation(0.04, 0.0, 0.0, 1.0)),NSValue(CATransform3D: CATransform3DMakeRotation(-0.04 , 0, 0, 1))] transformAnim.autoreverses = true transformAnim.duration = (Double(indexPath.row)%2) == 0 ? 0.115 : 0.105 transformAnim.repeatCount = Float.infinity self.layer.addAnimation(transformAnim, forKey: "transform") 

目标C: –

 -(CAKeyframeAnimation *)wiggleView { CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"transform"]; CGFloat wobbleAngle = 0.04f; NSValue* valLeft = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(wobbleAngle, 0.0f, 0.0f, 1.0f)]; NSValue* valRight = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(-wobbleAngle, 0.0f, 0.0f, 1.0f)]; animation.values = [NSArray arrayWithObjects:valLeft, valRight, nil]; animation.autoreverses = YES; animation.duration = 0.125; animation.repeatCount = HUGE_VALF; return animation; } 

在Swift 3中重写了Sebastien的答案。

 let wiggleBounceY = 4.0 let wiggleBounceDuration = 0.12 let wiggleBounceDurationVariance = 0.025 let wiggleRotateAngle = 0.06 let wiggleRotateDuration = 0.10 let wiggleRotateDurationVariance = 0.025 func randomize(interval: TimeInterval, withVariance variance: Double) -> Double{ let random = (Double(arc4random_uniform(1000)) - 500.0) / 500.0 return interval + variance * random } func startWiggle(for view: UIView){ //Create rotation animation let rotationAnim = CAKeyframeAnimation(keyPath: "transform.rotation.z") rotationAnim.values = [-wiggleRotateAngle, wiggleRotateAngle] rotationAnim.autoreverses = true rotationAnim.duration = randomize(interval: wiggleRotateDuration, withVariance: wiggleRotateDurationVariance) rotationAnim.repeatCount = HUGE //Create bounce animation let bounceAnimation = CAKeyframeAnimation(keyPath: "transform.translation.y") bounceAnimation.values = [wiggleBounceY, 0] bounceAnimation.autoreverses = true bounceAnimation.duration = randomize(interval: wiggleBounceDuration, withVariance: wiggleBounceDurationVariance) bounceAnimation.repeatCount = HUGE //Apply animations to view UIView.animate(withDuration: 0) { view.layer.add(rotationAnim, forKey: "rotation") view.layer.add(bounceAnimation, forKey: "bounce") view.transform = .identity } } func stopWiggle(for view: UIView){ view.layer.removeAllAnimations() } 
  func startWiggling() { deleteButton.isHidden = false guard contentView.layer.animation(forKey: "wiggle") == nil else { return } guard contentView.layer.animation(forKey: "bounce") == nil else { return } let angle = 0.04 let wiggle = CAKeyframeAnimation(keyPath: "transform.rotation.z") wiggle.values = [-angle, angle] wiggle.autoreverses = true wiggle.duration = randomInterval(0.1, variance: 0.025) wiggle.repeatCount = Float.infinity contentView.layer.add(wiggle, forKey: "wiggle") let bounce = CAKeyframeAnimation(keyPath: "transform.translation.y") bounce.values = [4.0, 0.0] bounce.autoreverses = true bounce.duration = randomInterval(0.12, variance: 0.025) bounce.repeatCount = Float.infinity contentView.layer.add(bounce, forKey: "bounce") } func stopWiggling() { deleteButton.isHidden = true contentView.layer.removeAllAnimations() } 

看看这个iOS SpingBoard的例子

编辑paiego的代码,以适应我的需求:视觉错误animation反馈在用户的行动(点击)。 它会发生一次 – 它不是一个像SpringBoard应用程序编辑摆动animation不断摇摆。

 - (CAAnimation *)shakeAnimation { CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform"]; CGFloat wobbleAngle = 0.06f; NSValue *valLeft; NSValue *valRight; NSMutableArray *values = [NSMutableArray new]; for (int i = 0; i < 5; i++) { valLeft = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(wobbleAngle, 0.0f, 0.0f, 1.0f)]; valRight = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(-wobbleAngle, 0.0f, 0.0f, 1.0f)]; [values addObjectsFromArray:@[valLeft, valRight]]; wobbleAngle*=0.66; } animation.values = [values copy]; animation.duration = 0.7; return animation; } 

用法:

 [your_view.layer addAnimation:[self shakeAnimation] forKey:@""]; //do the shake animation your_view.transform = CGAffineTransformIdentity; //return the view back to original 

希望这可以帮助别人。

在另一个线程回答了一个Swift 4版本,显然是苹果自己的algorithm逆向工程: https : //stackoverflow.com/a/47730519/5018607