iOS动画之水波动画

  • 前言:现在很多app为了提供好的交互效果给用户,通常都会通过添加动画效果来达到目的。一个好的动画效果往往会起到神来之笔的作用。而在IOS中动画效果也是丰富多彩的,我准备在后续的笔记中详细的记录那些动画。
  • 今天我们就来实现一下在IOS中的水波动画。先上效果图:
  • 最开始看到这个效果确实有点难的,不过如果对正弦公式比较了解的话实现起来也挺简单的。

    • 高中知识:y = Asin(wx + θ) + k;

    • 其中A:代表振幅; w:角频率,和周期的关系是:T = 2π/|w| ;θ:初相,相对于标准的正弦公式y = sin(x)而言,θ代表

    • 标准的正弦公式y = sin(x)在水平(x轴)方向上的整体移动,即左加右减;k:偏距,代表标准的正弦公式y = sin(x)在 垂直(y轴)方向上的整体移动,即上加下减。

    • 由表达式 y = sin(x)我们知道:在[0,2π]的区间上绘制一个完整的正弦波形,周期刚好是2π(T= 2π/|w|) 这里w = 1;绘制2个完整的正弦波形,周期为π。所以可以把w理解成完整波形的个数。由此可以得出:在区间[0,waveWidth]上绘制n个完整的波形,w = 2π * n / waveWidth。另外还要注意一点就是UIKit框架坐标轴是向下的。

    • 上面的知识也只是对正弦公式进行回顾。怎么样才能得到波形效果呢?关键点就在初相θ身上。

    • 下面这张图是正弦公式:y = sin(x)的图谱:


      我们把初相θ向左移动1个单位长度得到公式:y = sin(x + 1)的图谱:


      比较这两张图谱,我们可以从中发现:要想实现波形震荡效果,我们只需不断变化初相θ的值,然后不断刷新屏幕即可。

    • CADisplayLink:这个定时器的刷新频率是60HZ,即每秒可以对屏幕进行60次刷新,我们肉眼是感觉不出刷新间隔的时差的。
      整个实现过程的代码如下:

@interface JGWaterWaveAnimation()
{
    //振幅--这个决定波形的起伏高度
    CGFloat _waterAmplitude;
    //频率--这个决定波形的宽度
    CGFloat _waterFrequency;
    //初相:这个决定了波形水平移动的速度
    CGFloat _waterEpoch;
    //偏距--调节距离顶部的高度
    CGFloat _waterSetover;
    //定时器
    CADisplayLink *_timer;
    
    //波形整个的宽度
    CGFloat _waterWaveWidth;
    //波形的整个高度
    CGFloat _waterWaveHeight;
}
/**layer*/
@property(strong,nonatomic)CAShapeLayer *waterShapeLayer;
@end
@implementation JGWaterWaveAnimation
- (instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        
        //default
        _waterAmplitude = 15.0;
        //假设在frame的长度上出现3个完整的波形:注意这里乘以0.5出现震荡效果,如果不乘以0.5只会出现波形平移的效果。
        _waterFrequency = 2 *M_PI * 3 / frame.size.width *0.5;
        _waterEpoch = 0.0;
        _waterSetover = 20.0;
        
        _waterWaveWidth = CGRectGetWidth(self.frame);
        _waterWaveHeight = CGRectGetHeight(self.frame);
        
        [self.layer addSublayer:self.waterShapeLayer];
        //初始化定时器
        _timer = [CADisplayLink displayLinkWithTarget:[YYWeakProxy proxyWithTarget:self] selector:@selector(waterWaveAnimation)];
        [_timer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
    }
    return self;
}
- (void)waterWaveAnimation{
    
    //核心代码:
    _waterEpoch += 0.08;
    //path
    UIBezierPath *waterWavePath = [UIBezierPath bezierPath];
    [waterWavePath moveToPoint:CGPointMake(0, 0)];
    for (CGFloat x = 0; x < _waterWaveWidth; x ++) {
        CGFloat y = _waterAmplitude * sinf(_waterFrequency * x + _waterEpoch) + _waterSetover;
        [waterWavePath addLineToPoint:CGPointMake(x, y)];
    }
    [waterWavePath addLineToPoint:CGPointMake(_waterWaveWidth, _waterWaveHeight)];
    [waterWavePath addLineToPoint:CGPointMake(0, _waterWaveHeight)];
    [waterWavePath closePath];
    
    self.waterShapeLayer.path = waterWavePath.CGPath;
}
- (CAShapeLayer *)waterShapeLayer{
    if (!_waterShapeLayer) {
        _waterShapeLayer = [CAShapeLayer layer];
        _waterShapeLayer.frame = self.bounds;
        _waterShapeLayer.fillColor = [UIColor colorWithRed:52/255.0 green:152/255.0 blue:219/255.0 alpha:1.0].CGColor;
        _waterShapeLayer.strokeColor = [UIColor clearColor].CGColor;
    }
    return _waterShapeLayer;
}
- (void)dealloc{
    
    [_timer invalidate];
    _timer = nil;
}
@end

原文:https://blog.csdn.net/h2282802627/article/details/79116601

你可能感兴趣的:(iOS动画之水波动画)