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下载

发布了93 篇原创文章 · 获赞 21 · 访问量 25万+
展开阅读全文

iOS CAShapeLayerUIBezierPath无限绘制图线如何不卡

12-22

现在公司有一个要求:连接蓝牙BLE4.0之后,获取传递过来的数据,然后以点的形式连接成线。 我采用的是CAShapeLayer和UIBezierPath绘制曲线,当一开始点比较少的时候,可以非常流畅的把线画出来 但是当点的数目达到3000左右,就会开始卡顿。 因为我们的数据是每秒25个数据,在scrollView上显示的时候回非常卡顿,请问有什么好办法来解决这个问题呢???? 以下是绘制的代码: UIBezierPath *path = [[UIBezierPath alloc] init]; path.usesEvenOddFillRule = YES; NSString * tt=nil; float height=self.topScrollView.frame.size.height; if (objc.BLE_View.minusRangeValue==0) { tt=[NSString stringWithFormat:@"{%.2f,%.2f}",timer_number*1.2,objc.BLE_View.positive_k*height*(1-[string floatValue]/[objc.BLE_View.positiveRangeValue floatValue])]; } else { if (isPositive) { tt=[NSString stringWithFormat:@"{%.2f,%.2f}",timer_number*1.2,objc.BLE_View.positive_k*height*(1-[string floatValue]/[objc.BLE_View.positiveRangeValue floatValue])]; } else { tt=[NSString stringWithFormat:@"{%.2f,%.2f}",timer_number*1.2,objc.BLE_View.minus_k*height*(1+[string floatValue]/[objc.BLE_View.minusRangeValue floatValue])]; } } if (!pointLast.x) { pointLast=CGPointFromString(tt); [path moveToPoint:pointLast]; [path addLineToPoint:pointLast]; } else { [path moveToPoint:pointLast]; [path addLineToPoint:pointLast]; [path addLineToPoint:CGPointFromString(tt)]; } //create shape layer CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.drawsAsynchronously=YES; shapeLayer.strokeColor = [UIColor greenColor].CGColor; shapeLayer.fillColor = [UIColor whiteColor].CGColor; shapeLayer.lineWidth = 3; shapeLayer.lineJoin = kCALineJoinRound;//终点处理 shapeLayer.lineCap = kCALineCapRound;//线条拐角 shapeLayer.path = path.CGPath; //add it to our view [shapeLayerArr addObject:shapeLayer]; dispatch_sync(dispatch_get_main_queue(), ^{ [_topScrollView.layer addSublayer:shapeLayer]; // 设置layer的animation _topScrollView.layer.shouldRasterize = YES; NSLog(@"------》%f,-------》%f",pointLast.x-10,pointLast.y-10); [_topScrollView setNeedsDisplayInRect:CGRectMake(pointLast.x-10, pointLast.y-10, 40, 40)]; [_topScrollView.layer setNeedsDisplayInRect:CGRectMake(pointLast.x-10, pointLast.y-10, 40, 40)]; if (pointLast.x>_topScrollView.contentSize.width) { _topScrollView.contentSize=CGSizeMake(_topScrollView.contentSize.width+_topScrollView.frame.size.width, 0); _topScrollView.contentOffset=CGPointMake(pointLast.x, 0); } pointLast=CGPointFromString(tt); }); 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览