IOS绘制动画颜色渐变折线条_IOS

先给大家展示下效果图:

概述

现状

折线图的应用比较广泛,为了增强用户体验,很多应用中都嵌入了折线图。折线图可以更加直观的表示数据的变化。网络上有很多绘制折线图的demo,有的也使用了动画,但是线条颜色渐变的折线图的demo少之又少,甚至可以说没有。该Blog阐述了动画绘制线条颜色渐变的折线图的实现方案,以及折线图线条颜色渐变的实现原理,并附以完整的示例。

成果

本人已将折线图封装到了一个UIView子类中,并提供了相应的接口。该自定义折线图视图,基本上可以适用于大部分需要集成折线图的项目。若你遇到相应的需求可以直接将文件拖到项目中,调用相应的接口即可

项目文件中包含了大量的注释代码,若你的需求与折线图的实现效果有差别,那么你可以对项目文件的进行修改,也可以依照思路定义自己的折线图视图

Blog中涉及到的知识点

CALayer

图层,可以简单的看做一个不接受用户交互的UIView

每个图层都具有一个CALayer类型mask属性,作用与蒙版相似

Blog中主要用到的CALayer子类有

CAGradientLayer,绘制颜色渐变的背景图层

CAShapeLayer,绘制折线图

CAAnimation

核心动画的基类(不可实例化对象),实现动画操作
Quartz 2D
一个二维的绘图引擎,用来绘制折线(Path)和坐标轴信息(Text)

实现思路

折线图视图

整个折线图将会被自定义到一个UIView子类中

坐标轴绘制

坐标轴直接绘制到折线图视图上,在自定义折线图视图的 drawRect 方法中绘制坐标轴相关信息(线条和文字)

注意坐标系的转换

线条颜色渐变

失败的方案

开始的时候,为了实现线条颜色渐变,我的思考方向是,如何改变路径(UIBezierPath)的渲染颜色(strokeColor)。但是strokeColor只可以设置一种,所以最终无法实现线条颜色的渐变。

成功的方案

在探索过程中找到了CALayer的CALayer类型的mask()属性,最终找到了解决方案,即:使用UIView对象封装渐变背景视图(frame为折线图视图的减去坐标轴后的frame),创建一个CAGradientLayer渐变图层添加到背景视图上。

创建一个CAShapeLayer对象,用于绘制线条,线条的渲染颜色(strokeColor)为whiteColor,填充颜色(fillColor)为clearColor,从而显示出渐变图层的颜色。将CAShapeLayer对象设置为背景视图的mask属性,即背景视图的蒙版。

折线

使用 UIBezierPath 类来绘制折线

折线转折处尖角的处理,使用 kCALineCapRound 与 kCALineJoinRound 设置折线转折处为圆角

折线起点与终点的圆点的处理,可以直接在 UIBezierPath 对象上添加一个圆,设置远的半径为路径宽度的一半,从而保证是一个实心的圆而不是一个圆环

折线转折处的点

折线转折处点使用一个类来描述(不使用CGPoint的原因是:折线转折处的点需要放到一个数组中)

坐标轴信息

X轴、Y轴的信息分别放到一个数组中

X轴显示的是最近七天的日期,Y轴显示的是最近七天数据变化的幅度

动画

使用CABasicAnimation类来完成绘制折线图时的动画

需要注意的是,折线路径在一开始时需要社会线宽为0,开始绘制时才设置为适当的线宽,保证一开折线路径是隐藏的

标签

在动画结束时,向折线图视图上添加一个标签(UIButton对象),显示折线终点的信息

标签的位置,需要根据折线终点的位置计算

具体实现

折线转折处的点

使用一个类来描述折线转折处的点,代码如下:

// 接口
/** 折线图上的点 */
@interface IDLineChartPoint : NSObject
/** x轴偏移量 */
@property (nonatomic, assign) float x;
/** y轴偏移量 */
@property (nonatomic, assign) float y;
/** 工厂方法 */
+ (instancetype)pointWithX:(float)x andY:(float)y;
@end
// 实现
@implementation IDLineChartPoint
+ (instancetype)pointWithX:(float)x andY:(float)y {
IDLineChartPoint *point = [[self alloc] init];
point.x = x;
point.y = y;
return point;
}
@end

自定义折线图视图

折线图视图是一个自定义的UIView子类,代码如下:

// 接口
/** 折线图视图 */
@interface IDLineChartView : UIView
/** 折线转折点数组 */
@property (nonatomic, strong) NSMutableArray<IDLineChartPoint *> *pointArray;
/** 开始绘制折线图 */
- (void)startDrawlineChart;
@end
// 分类
@interface IDLineChartView ()
@end
// 实现
@implementation IDLineChartView
// 初始化
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// 设置折线图的背景色
self.backgroundColor = [UIColor colorWithRed:243/255.0 green:243/255.0 blue:243/255.0 alpha:1.0];
}
return self;
}
@end

效果如图

绘制坐标轴信息

与坐标轴绘制相关的常量

/** 坐标轴信息区域宽度 */
static const CGFloat kPadding = 25.0;
/** 坐标系中横线的宽度 */
static const CGFloat kCoordinateLineWith = 1.0;

在分类中添加与坐标轴绘制相关的成员变量

/** X轴的单位长度 */
@property (nonatomic, assign) CGFloat xAxisSpacing;
/** Y轴的单位长度 */
@property (nonatomic, assign) CGFloat yAxisSpacing;
/** X轴的信息 */
@property (nonatomic, strong) NSMutableArray<NSString *> *xAxisInformationArray;
/** Y轴的信息 */
@property (nonatomic, strong) NSMutableArray<NSString *> *yAxisInformationArray;

与坐标轴绘制相关的成员变量的get方法

- (CGFloat)xAxisSpacing {
if (_xAxisSpacing == 0) {
_xAxisSpacing = (self.bounds.size.width - kPadding) / (float)self.xAxisInformationArray.count;
}
return _xAxisSpacing;
}
- (CGFloat)yAxisSpacing {
if (_yAxisSpacing == 0) {
_yAxisSpacing = (self.bounds.size.height - kPadding) / (float)self.yAxisInformationArray.count;
}
return _yAxisSpacing;
}
- (NSMutableArray<NSString *> *)xAxisInformationArray {
if (_xAxisInformationArray == nil) {
// 创建可变数组
_xAxisInformationArray = [[NSMutableArray alloc] init];
// 当前日期和日历
NSDate *today = [NSDate date];
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
// 设置日期格式
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = @"MM-dd";
// 获取最近一周的日期
NSDateComponents *components = [[NSDateComponents alloc] init];
for (int i = -7; i<0; i++) {
components.day = i;
NSDate *dayOfLatestWeek = [currentCalendar dateByAddingComponents:components toDate:today options:0];
NSString *dateString = [dateFormatter stringFromDate:dayOfLatestWeek];
[_xAxisInformationArray addObject:dateString];
}
}
return _xAxisInformationArray;
}
- (NSMutableArray<NSString *> *)yAxisInformationArray {
if (_yAxisInformationArray == nil) {
_yAxisInformationArray = [NSMutableArray arrayWithObjects:@"0", @"10", @"20", @"30", @"40", @"50", nil];
}
return _yAxisInformationArray;
}

绘制坐标轴的相关信息

- (void)drawRect:(CGRect)rect {
// 获取上下文
CGContextRef context = UIGraphicsGetCurrentContext();
// x轴信息
[self.xAxisInformationArray enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
// 计算文字尺寸
UIFont *informationFont = [UIFont systemFontOfSize:10];
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
attributes[NSForegroundColorAttributeName] = [UIColor colorWithRed:158/255.0 green:158/255.0 blue:158/255.0 alpha:1.0];
attributes[NSFontAttributeName] = informationFont;
CGSize informationSize = [obj sizeWithAttributes:attributes];
// 计算绘制起点
float drawStartPointX = kPadding + idx * self.xAxisSpacing + (self.xAxisSpacing - informationSize.width) * 0.5;
float drawStartPointY = self.bounds.size.height - kPadding + (kPadding - informationSize.height) / 2.0;
CGPoint drawStartPoint = CGPointMake(drawStartPointX, drawStartPointY);
// 绘制文字信息
[obj drawAtPoint:drawStartPoint withAttributes:attributes];
}];
// y轴
[self.yAxisInformationArray enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
// 计算文字尺寸
UIFont *informationFont = [UIFont systemFontOfSize:10];
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
attributes[NSForegroundColorAttributeName] = [UIColor colorWithRed:158/255.0 green:158/255.0 blue:158/255.0 alpha:1.0];
attributes[NSFontAttributeName] = informationFont;
CGSize informationSize = [obj sizeWithAttributes:attributes];
// 计算绘制起点
float drawStartPointX = (kPadding - informationSize.width) / 2.0;
float drawStartPointY = self.bounds.size.height - kPadding - idx * self.yAxisSpacing - informationSize.height * 0.5;
CGPoint drawStartPoint = CGPointMake(drawStartPointX, drawStartPointY);
// 绘制文字信息
[obj drawAtPoint:drawStartPoint withAttributes:attributes];
// 横向标线
CGContextSetRGBStrokeColor(context, 231 / 255.0, 231 / 255.0, 231 / 255.0, 1.0);
CGContextSetLineWidth(context, kCoordinateLineWith);
CGContextMoveToPoint(context, kPadding, self.bounds.size.height - kPadding - idx * self.yAxisSpacing);
CGContextAddLineToPoint(context, self.bounds.size.width, self.bounds.size.height - kPadding - idx * self.yAxisSpacing);
CGContextStrokePath(context);
}];
}

效果如图

渐变背景视图

在分类中添加与背景视图相关的常量

/** 渐变背景视图 */
@property (nonatomic, strong) UIView *gradientBackgroundView;
/** 渐变图层 */
@property (nonatomic, strong) CAGradientLayer *gradientLayer;
/** 颜色数组 */
@property (nonatomic, strong) NSMutableArray *gradientLayerColors;

在初始化方法中添加调用设置背景视图方法的代码

设置渐变视图方法的具体实现

- (void)drawGradientBackgroundView {
// 渐变背景视图(不包含坐标轴)
self.gradientBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(kPadding, 0, self.bounds.size.width - kPadding, self.bounds.size.height - kPadding)];
[self addSubview:self.gradientBackgroundView];
/** 创建并设置渐变背景图层 */
//初始化CAGradientlayer对象,使它的大小为渐变背景视图的大小
self.gradientLayer = [CAGradientLayer layer];
self.gradientLayer.frame = self.gradientBackgroundView.bounds;
//设置渐变区域的起始和终止位置(范围为0-1),即渐变路径
self.gradientLayer.startPoint = CGPointMake(0, 0.0);
self.gradientLayer.endPoint = CGPointMake(1.0, 0.0);
//设置颜色的渐变过程
self.gradientLayerColors = [NSMutableArray arrayWithArray:@[(__bridge id)[UIColor colorWithRed:253 / 255.0 green:164 / 255.0 blue:8 / 255.0 alpha:1.0].CGColor, (__bridge id)[UIColor colorWithRed:251 / 255.0 green:37 / 255.0 blue:45 / 255.0 alpha:1.0].CGColor]];
self.gradientLayer.colors = self.gradientLayerColors;
//将CAGradientlayer对象添加在我们要设置背景色的视图的layer层
[self.gradientBackgroundView.layer addSublayer:self.gradientLayer];
}

效果如图

折线

在分类中添加与折线绘制相关的成员变量

/** 折线图层 */
@property (nonatomic, strong) CAShapeLayer *lineChartLayer;
/** 折线图终点处的标签 */
@property (nonatomic, strong) UIButton *tapButton;

在初始化方法中添加调用设置折线图层方法的代码

[self setupLineChartLayerAppearance];

设置折线图层方法的具体实现

- (void)setupLineChartLayerAppearance {
/** 折线路径 */
UIBezierPath *path = [UIBezierPath bezierPath];
[self.pointArray enumerateObjectsUsingBlock:^(IDLineChartPoint * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
// 折线
if (idx == 0) {
[path moveToPoint:CGPointMake(self.xAxisSpacing * 0.5 + (obj.x - 1) * self.xAxisSpacing, self.bounds.size.height - kPadding - obj.y * self.yAxisSpacing)];
} else {
[path addLineToPoint:CGPointMake(self.xAxisSpacing * 0.5 + (obj.x - 1) * self.xAxisSpacing, self.bounds.size.height - kPadding - obj.y * self.yAxisSpacing)];
}
// 折线起点和终点位置的圆点
if (idx == 0 || idx == self.pointArray.count - 1) {
[path addArcWithCenter:CGPointMake(self.xAxisSpacing * 0.5 + (obj.x - 1) * self.xAxisSpacing, self.bounds.size.height - kPadding - obj.y * self.yAxisSpacing) radius:2.0 startAngle:0 endAngle:2 * M_PI clockwise:YES];
}
}];
/** 将折线添加到折线图层上,并设置相关的属性 */
self.lineChartLayer = [CAShapeLayer layer];
self.lineChartLayer.path = path.CGPath;
self.lineChartLayer.strokeColor = [UIColor whiteColor].CGColor;
self.lineChartLayer.fillColor = [[UIColor clearColor] CGColor];
// 默认设置路径宽度为0,使其在起始状态下不显示
self.lineChartLayer.lineWidth = 0;
self.lineChartLayer.lineCap = kCALineCapRound;
self.lineChartLayer.lineJoin = kCALineJoinRound;
// 设置折线图层为渐变图层的mask
self.gradientBackgroundView.layer.mask = self.lineChartLayer;
}

效果如图(初始状态不显示折线)

动画的开始与结束

动画开始

/** 动画开始,绘制折线图 */
- (void)startDrawlineChart {
// 设置路径宽度为4,使其能够显示出来
self.lineChartLayer.lineWidth = 4;
// 移除标签,
if ([self.subviews containsObject:self.tapButton]) {
[self.tapButton removeFromSuperview];
}
// 设置动画的相关属性
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
pathAnimation.duration = 2.5;
pathAnimation.repeatCount = 1;
pathAnimation.removedOnCompletion = NO;
pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];
// 设置动画代理,动画结束时添加一个标签,显示折线终点的信息
pathAnimation.delegate = self;
[self.lineChartLayer addAnimation:pathAnimation forKey:@"strokeEnd"];
}

动画结束,添加标签

/** 动画结束时,添加一个标签 */
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
if (self.tapButton == nil) { // 首次添加标签(避免多次创建和计算)
CGRect tapButtonFrame = CGRectMake(self.xAxisSpacing * 0.5 + ([self.pointArray[self.pointArray.count - 1] x] - 1) * self.xAxisSpacing + 8, self.bounds.size.height - kPadding - [self.pointArray[self.pointArray.count - 1] y] * self.yAxisSpacing - 34, 30, 30);

self.tapButton = [[UIButton alloc] initWithFrame:tapButtonFrame];
self.tapButton.enabled = NO;
[self.tapButton setBackgroundImage:[UIImage imageNamed:@"bubble"] forState:UIControlStateDisabled];
[self.tapButton.titleLabel setFont:[UIFont systemFontOfSize:10]];
[self.tapButton setTitle:@"20" forState:UIControlStateDisabled];
}
[self addSubview:self.tapButton];
}

集成折线图视图

创建折线图视图

添加成员变量

/** 折线图 */
@property (nonatomic, strong) IDLineChartView *lineCharView;

在viewDidLoad方法中创建折线图并添加到控制器的view上

self.lineCharView = [[IDLineChartView alloc] initWithFrame:CGRectMake(35, 164, 340, 170)];
[self.view addSubview:self.lineCharView];

添加开始绘制折线图视图的按钮

添加成员变量

/** 开始绘制折线图按钮 */
@property (nonatomic, strong) UIButton *drawLineChartButton;

在viewDidLoad方法中创建开始按钮并添加到控制器的view上

self.drawLineChartButton = [UIButton buttonWithType:UIButtonTypeSystem];
self.drawLineChartButton.frame = CGRectMake(180, 375, 50, 44);
[self.drawLineChartButton setTitle:@"开始" forState:UIControlStateNormal];
[self.drawLineChartButton addTarget:self action:@selector(drawLineChart) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.drawLineChartButton];
开始按钮的点击事件
// 开始绘制折线图
- (void)drawLineChart {
[self.lineCharView startDrawlineChart];
}

好了,关于IOS绘制动画颜色渐变折线条就给大家介绍这么多,希望对大家有所帮助!

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索ios折线条
, 渐变线条
绘制折线图
ios绘制线条动画效果、canvas绘制流动的线条、渐变线条、ps渐变线条、ai线条渐变,以便于您获取更多的相关知识。

时间: 2024-10-30 23:02:59

IOS绘制动画颜色渐变折线条_IOS的相关文章

iOS快速实现环形渐变进度条_IOS

前言 进度条相信我们大家都不陌生,往往我们很多时候需要使用到圆形进度条.这篇文章给大家分享了利用iOS如何快速实现环形进度条,下面来一起看看. 一:先制作一个不带颜色渐变的进度条 自定义一个cycleView,在.m 中实现drawRect方法 - (void)drawRect:(CGRect)rect { CGContextRef ctx = UIGraphicsGetCurrentContext();//获取上下文 CGPoint center = CGPointMake(100, 100)

iOS基础动画教程分享_IOS

iOS的动画多种多样,动画做的好的应用会更加吸引人,用起来也会更加炫目,本文介绍iOS几种基础动画,单个讲解便于理解,但真正使用时,结合起来用会看起来更加帅,这就看具体的应用场景和大家的想象力啦. 所有的基础动画都给予UIView一个基础的方法:animateWithDuration.这个方法可以包含一个代码块,里面设置要改变的东西,在执行的时候iOS会自动以动画的形式展现出来,代码如下: [UIView animateWithDuration:1 animations:^{ // 要执行的动作

iOS 利用动画和贝塞尔实现咻咻效果_IOS

先上效果图: 圆形 方形 思路分析: 这四种风格其实就是两种, 一种是动画效果在视图View的内部, 另一种是在视图的外部! 我们可以尝试封装自定义 View 设置相关属性去实现这两个风格. 点击时候触及动画, 说明要在这个 View 上添加手势! 分析动画效果其实是两种, 第一种是视图的比例由小到大,第二种是动画显示效果是渐渐变暗! 那么我们可以把两种效果写到一个动画组中!还有一个问题是效果的形状, 也就是 Layer 动画展示的形状有方形有圆形, 这个形状就需要我们思考如何去绘制和判断! 代

带动画渐进效果与颜色渐变的圆弧进度控件设计

带动画渐进效果与颜色渐变的圆弧进度控件设计      今天帮朋友写了一个小巧的圆弧进度控件,控件十分简单,主要设计思路采用CAShapeLayer来创建控件圆弧形状,使用CAGradientLayer来进行颜色渐变的渲染,两者结合来创建出颜色渐变的圆弧进度条控件,关于进度动画采用CoreAnimation动画处理.控件进行了简洁的封装,提供了面向使用的接口,需要的朋友可以自取,Demo地址如下: http://pan.baidu.com/s/1gfqDbtp.       控件中主要提供了,改变

js实现按钮颜色渐变动画效果_javascript技巧

本文实例讲述了js实现按钮颜色渐变动画效果的方法.分享给大家供大家参考.具体如下: 这里演示js实现按钮慢慢变色的方法,鼠标移到按钮上,按钮的背景色就发生变化,是慢慢的变化,点击按钮会打开指定链接,这里主要是演示按钮变色的代码实现方法. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/js-button-cha-color-animate-codes/ 具体代码如下: <HTML><HEAD><TITLE>按钮慢慢变色&

iOS 动画 —— 礼花效果实例详细_IOS

CAEmitterLayer 提供了一个基于 Core Animation 的粒子发射系统,使用它可以实现各种各样的粒子动画效果.此处的礼花效果,就是基于 CAEmitterLayer 的. fire.gif - (void)viewDidLoad { [super viewDidLoad]; [self makeFireworksDisplay]; } - (void)makeFireworksDisplay { // 粒子发射系统 的初始化 CAEmitterLayer *fireworks

iOS 基本动画、关键帧动画、利用缓动函数实现物理动画效果_IOS

iOS基本动画/关键帧动画/利用缓动函数实现物理动画效果 先说下基本动画部分 基本动画部分比较简单, 但能实现的动画效果也很局限 使用方法大致为: #1. 创建原始UI或者画面 #2. 创建CABasicAnimation实例, 并设置keypart/duration/fromValue/toValue #3. 设置动画最终停留的位置 #4. 将配置好的动画添加到layer层中 举个例子, 比如实现一个圆形从上往下移动, 上代码: //设置原始画面 UIView *showView = [[UI

iOS开发中常用的各种动画、页面切面效果_IOS

今天主要用到的动画类是CALayer下的CATransition至于各种动画类中如何继承的在这也不做赘述,网上的资料是一抓一大把.好废话少说切入今天的正题. 一.封装动画方法 1.用CATransition实现动画的封装方法如下,每句代码是何意思,请看注释之. #pragma CATransition动画实现 - (void) transitionWithType:(NSString *) type WithSubtype:(NSString *) subtype ForView : (UIVi

利用iOS绘制图片生成随机验证码示例代码_IOS

先来看看效果图 实现方法 .h文件 @property (nonatomic, retain) NSArray *changeArray; @property (nonatomic, retain) NSMutableString *changeString; @property (nonatomic, retain) UILabel *codeLabel; -(void)changeCode; @end .m文件 @synthesize changeArray = _changeArray;