01 窗口抖动
创建一个NSWindow的分类,我取名为NSWindow+Animation
自定义抖屏方法,实现beginShakeAnimation方法,如下截图所示:
为了方便大家取用,摘抄代码复制如下:
static NSInteger const numberOfShakes = 20;
static float const durationOfShake = 0.5f;
static float const vigourOfShake = 0.01f;
- (void)beginShakeAnimation
{
CGRect frame = self.frame;
CAKeyframeAnimation *shakeAnimation = [CAKeyframeAnimation animation];
CGMutablePathRef shakePath = CGPathCreateMutable();
CGPathMoveToPoint(shakePath, NULL, NSMinX(frame), NSMinY(frame));
int index;
for (index = 0; index < numberOfShakes; ++index)
{
CGPathAddLineToPoint(shakePath, NULL, NSMinX(frame) - frame.size.width * vigourOfShake, NSMinY(frame));
CGPathAddLineToPoint(shakePath, NULL, NSMinX(frame) + frame.size.width * vigourOfShake, NSMinY(frame));
}
CGPathCloseSubpath(shakePath);
shakeAnimation.path = shakePath;
shakeAnimation.duration = durationOfShake;
[self setAnimations:@{@"frameOrigin" : shakeAnimation}];
[[self animator] setFrameOrigin:self.frame.origin];
}
02 视图抖动
如果你的需求不是整个窗口抖动,而是某个视图抖动,就需要用layer的关键帧动画来实现。
创建一个NSView的分类,我取名为NSView+Animation
自定义抖屏方法,实现beginShakeAnimation方法,如下截图所示:
为了方便大家取用,摘抄代码复制如下:
//角度转化为弧度
#define kToRadian(x) (M_PI/180 * (x))
- (void)beginShakeAnimation
{
//视图抖动
CAKeyframeAnimation *keyframeAni = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];
keyframeAni.duration = 0.2;
//关键部分角度
keyframeAni.values = @[@(kToRadian(5)),@(kToRadian(0)),@(kToRadian(-5)),@(kToRadian(0)),@(kToRadian(5))];
keyframeAni.repeatCount = 5;
NSRect viewRect = self.frame;
CGFloat posX = NSMinX(viewRect) + NSWidth(viewRect) * 0.5;
CGFloat posY = NSMinY(viewRect) + NSHeight(viewRect) * 0.5;
self.layer.position = CGPointMake(posX, posY);
self.layer.anchorPoint = CGPointMake(0.5, 0.5);
[self.layer addAnimation:keyframeAni forKey:@"key"];
}
需要注意的是:mac应用的关键帧动画圆点是视图原点,ios的圆点视图是中心,所以mac需要修改一下position和anchorPoint。
总结:如果是窗口抖动,使用NSWindow的setAnimations方法;如果是视图抖动,使用NSView.layer的关键帧动画。