1. 程式人生 > >OC實現水波紋動畫

OC實現水波紋動畫

               

用OC原生的貝塞爾曲線來實現該效果,下面直接上程式碼:

- (void)showWatterRippleAnimation {
    btnWatter = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 120, 120)];
    btnWatter.layer.cornerRadius = 60.f;
    btnWatter.center = self.view.center;
    btnWatter.layer.borderColor = [UIColor darkGrayColor].CGColor;
    btnWatter.layer.borderWidth = 1;
    btnWatter.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:btnWatter];
    
    [self addAnimationView];
    //如果要實現圖2效果,則開啟此程式碼
    //    _animationTimer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(addAnimationView) userInfo:nil repeats:YES];
    //    [_animationTimer fire];
}

- (void)addAnimationView {
    _animationViewsArr = [NSMutableArray array];
    //繪製3條貝塞爾曲線儲存起來進行動畫處理
    for (int i = 0; i < 3; i++) {
        CAShapeLayer *layer = [self getShapeLayer];
        [_animationViewsArr addObject:layer];
        [btnWatter.layer addSublayer:layer];
        [self addAnimationWithShapeLayer:layer delay:i*spaceTime];
    }
}

//將目標曲線做放大動畫
- (void)addAnimationWithShapeLayer:(CAShapeLayer*)layer delay:(CGFloat)delayTime
{
    CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    //修改變化大小
    scaleAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
    scaleAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.5, 1.5, 1)];
    
    //修改變化透明度
    CABasicAnimation *alphaAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    alphaAnimation.fromValue = @0.4;
    alphaAnimation.toValue = @0;
    
    //設定動畫
    CAAnimationGroup *animation = [CAAnimationGroup animation];
    animation.animations = @[scaleAnimation, alphaAnimation];
    animation.duration = 3 * spaceTime;
    animation.repeatCount = CGFLOAT_MAX;    //如果要實現圖2效果,設為1
    animation.beginTime = delayTime + CACurrentMediaTime();
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    animation.removedOnCompletion = NO;
    animation.fillMode = kCAFillModeForwards;
    [layer addAnimation:animation forKey:nil];
}

//以btnWatter為中心繪製貝塞爾曲線
- (CAShapeLayer*)getShapeLayer
{
    CGRect pathFrame = CGRectMake(-CGRectGetMidX(btnWatter.bounds), -CGRectGetMidY(btnWatter.bounds), btnWatter.frame.size.width, btnWatter.frame.size.height);
    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:pathFrame cornerRadius:btnWatter.frame.size.width / 2];
    CAShapeLayer *pathLayer = [CAShapeLayer layer];
    pathLayer.lineWidth = 1;
    pathLayer.position = CGPointMake(btnWatter.frame.size.width/2, btnWatter.frame.size.height/2);
    pathLayer.opacity = 0.0f;
    pathLayer.strokeColor = [UIColor lightGrayColor].CGColor;
    pathLayer.path = path.CGPath;
    pathLayer.fillColor = nil; // 預設為blackColor
    return pathLayer;
}

需要注意的是,當動畫在進行的時候如果home再返回前臺,動畫會出現未知的效果。所以需要監聽一下進入後臺和回到前臺的通知,並且實現停止和開始的方法:

- (void)startAnimation
{
    for (int i = 0; i < 3; i++) {
        CAShapeLayer *layer = self.animationViewsArr[i];
        layer.hidden = NO;
    }
}

- (void)stopAnimation
{
    for (int i = 0; i < 3; i++) {
        CAShapeLayer *layer = self.animationViewsArr[i];
        layer.hidden = YES;
    }
}