iOS CAShapeLayer 绘制柱状图动画

图形绘制

线条绘制

单轨迹线条绘制设置线宽,动画进可以通过 KeyPath 设置为 strokeEnd 进行渲染,达到动态渲染的目的

image.png
    // 绘制轨迹
    UIBezierPath *bezierPath = [UIBezierPath bezierPath];
    [bezierPath moveToPoint:CGPointMake(200, 200)];
    [bezierPath addLineToPoint:CGPointMake(150, 100)];

    //  轨迹渲染
    CAShapeLayer * layer = [CAShapeLayer layer];
    layer.fillColor = [UIColor redColor].CGColor;
    layer.strokeColor = [UIColor redColor].CGColor;
    layer.strokeStart = 0;
    layer.strokeEnd = 1;
    layer.zPosition = 1;
    layer.lineWidth = 1;
    layer.path  = bezierPath.CGPath;
    [self.view.layer addSublayer:layer];

  // 轨迹动画
   CABasicAnimation * pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    pathAnimation.duration = 1.0f;
    pathAnimation.fromValue = @0.0f;
    pathAnimation.toValue = @1.0f;
    pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];//添加动画样式

  // 添加动画
 [layer addAnimation: pathAnimation  forKey:@"strokeEndAnimation"];

三角形绘制

简单绘制一个三角形,bezierPath 调用 closePath 时, 绘制的线路必须是闭合的,再调用 closePath 才能闭合,但是动画设置为 strokeEnd 却无效,需要重新设置动画组合 CAAnimationGroup 才能添加渲染动画

绘制如图图形


image.png
    // 绘制三角形
   UIBezierPath *bezierPath = [UIBezierPath bezierPath];
   [bezierPath moveToPoint:CGPointMake(200, 200)];
   [bezierPath addLineToPoint:CGPointMake(150, 100)];
   [bezierPath addLineToPoint:CGPointMake(250, 100)];
   [bezierPath closePath];

    // 填充红色颜色
    CAShapeLayer * layer = [CAShapeLayer layer];
    layer.fillColor = [UIColor redColor].CGColor;
    layer.strokeColor = [UIColor redColor].CGColor;
    layer.strokeStart = 0;
    layer.strokeEnd = 1;
    layer.zPosition = 1;
    layer.lineWidth = 1;
    layer.path  = bezierPath.CGPath;
    [self.view.layer addSublayer:layer];   

   // 添加动画
   [layer addAnimation:[self pathAnimation] forKey:@"strokeEndAnimation"];

折线图绘制

通过折线图绘制,可以满足部分柱状图的需求,同时添加延展动画


image.png

image.png
   // 起始位置
    CGFloat lastPointX = 100;
    // 单位宽度
    CGFloat itemWidth = 40;
    // 相邻间隙
    CGFloat itemPadding = 10;
    // 图标高度
    CGFloat chartHeight = 100;
    // 数据
    NSArray *dataArray = @[@180,@160,@140,@120,@160,@180,@200];
    // 最大值
    CGFloat maValue = [[dataArray valueForKeyPath:@"@max.floatValue"] floatValue];
    
    for (NSInteger index = 0; index < dataArray.count; index++) {
        NSInteger value = [dataArray[index] integerValue];
        CGFloat height = value  *  1.0 / maValue * chartHeight;
        CGFloat y =  200 - height;
        CGFloat x = lastPointX + itemWidth;
        // 轨迹绘制
        [bezierPath addLineToPoint:CGPointMake(lastPointX, y)];
        [bezierPath addLineToPoint:CGPointMake(x, y)];
        if (index != dataArray.count-1) {
            [bezierPath addLineToPoint:CGPointMake(x, 200)];
            [bezierPath moveToPoint:CGPointMake(x + itemPadding, 200)];
        } else {
            [bezierPath addLineToPoint:CGPointMake(x, 200)];
        }
        lastPointX = x+itemPadding;
    }
    
    //添加CAShapeLayer
    CAShapeLayer * layer = [CAShapeLayer layer];
    layer.fillColor = [UIColor redColor].CGColor;
    layer.strokeColor = [UIColor redColor].CGColor;
    layer.strokeStart = 0;
    layer.strokeEnd = 1;
    layer.zPosition = 1;
    layer.lineWidth = 1;
    layer.path  = bezierPath.CGPath;
    [self.view.layer addSublayer:layer];

    // 添加动画  animationGroup 为动画代码 
    [layer addAnimation:[self pathAnimation] forKey:@"strokeEndAnimation"];

动画复用
- (CAAnimationGroup *)pathAnimation {
 
    // 延展方向
    CABasicAnimation * pathAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale.y"];
    pathAnimation.fromValue = @0.0f;//动画开始位置
    pathAnimation.toValue = @1.0f;//动画停止位置

    // 延展值
    CABasicAnimation *posAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
    posAnimation.fromValue = [NSValue valueWithCGPoint:CGPointMake(0,200)];
    posAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(0,0)];

    // 动画组合
    CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
    animationGroup.animations = @[pathAnimation,posAnimation];
    animationGroup.duration = 0.3f;
    animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    animationGroup.removedOnCompletion = NO;
    animationGroup.fillMode = kCAFillModeForwards;
    return animationGroup;
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。