iOS CAShapeLayer + UIBezierPath 实现震动条调效果


一、实现原理

原理很简单:通过给Layer添加一个运动路径,使Layer在这个路径下一直重复运动即可;

二、代码

//动画名称
static NSString *AnimationName = @"ESSEQAnimation";

@implementation PlayingLineView
{
    //线宽度
    float _lineWidth;
    //线颜色
    UIColor *_lineColor;
    //线的集合
    NSMutableArray *_layerArr;
    //线的动画
    NSMutableArray *_animationArr;
}
//初始化震动调
-(instancetype)initWithFrame:(CGRect)frame lineWidth:(float)lineWidth lineColor:(UIColor*)lineColor
{
    self = [super initWithFrame:frame];
    if (self) {
        _lineWidth = lineWidth;
        _lineColor = lineColor;
        _layerArr = [NSMutableArray new];
        _animationArr = [NSMutableArray new];
        [self buildLayout];
    }
    return self;
}
//每一个震动条的运动路径
-(NSArray*)values
{
    return @[@[@1.0, @0.5, @0.1, @0.4, @0.7, @0.9, @1.0],
             @[@1.0, @0.8, @0.5, @0.1, @0.5, @0.7, @1.0],
             @[@1.0, @0.7, @0.4, @0.4, @0.7, @0.9, @1.0]];
}
//随机运动的时长
-(NSArray*)durations
{
    return @[@(0.9),@(1.0),@(0.9)];
}

//创建三个竖条
-(void)buildLayout
{
    float margin = (self.bounds.size.width - 3*_lineWidth)/4;
    float height = self.bounds.size.height;
    NSArray* layerHeight = @[@(0.6*height),@(0.8*height),@(0.9*height)];
    for (int i = 0; i < [self values].count; i++) {
        //初始化layer
        CAShapeLayer *layer = [[CAShapeLayer alloc] init];
        layer.fillColor = [UIColor clearColor].CGColor;
        layer.lineCap = kCALineCapRound;
        layer.strokeColor = _lineColor.CGColor;
        layer.frame = self.bounds;
        layer.lineWidth = _lineWidth;
        [self.layer addSublayer:layer];
        [_layerArr addObject:layer];
        
        //通过贝塞尔曲线设置layer的移动路径
        CGFloat pillarHeight = [layerHeight[i] floatValue];
        CGFloat x = (i+1)*margin + i*_lineWidth;
        CGPoint startPoint = CGPointMake(x, height);
        CGPoint toPoint = CGPointMake(x, height - pillarHeight);
        UIBezierPath * path = [UIBezierPath bezierPath];
        [path moveToPoint:startPoint];
        [path addLineToPoint:toPoint];
        layer.path = path.CGPath;
        
        //设置动画
        CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"strokeEnd"];
        animation.values = [self values][i];
        animation.duration = [[self durations][i] floatValue];
        animation.repeatCount = HUGE_VAL;
        animation.removedOnCompletion = false;//必须设为false否则会被销毁掉
        animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        [layer addAnimation:animation forKey:AnimationName];
        [_animationArr addObject:animation];
    }
}

//暂停
-(void)pause
{
    for (int i = 0; i<_layerArr.count; i++) {
        CAShapeLayer *layer = _layerArr[i];
        [layer removeAnimationForKey:AnimationName];
    }
}

//开始
-(void)start
{
    for (int i = 0; i<_layerArr.count; i++) {
        CAShapeLayer *layer = _layerArr[i];
        CAKeyframeAnimation *animation = _animationArr[i];
        [layer addAnimation:animation forKey:AnimationName];
    }
}

Demo下载

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页