iOS 绘图机制简介,Quartz 2D绘图用CGContextRef绘制音频波形图

释放双眼,带上耳机,听听看~!

简单说一下iOS的绘图机制。iOS的视图可以通过drawRect方法绘图,通过View的Layer(CALayer)图层来定制一个视图,每个layer展示一部分属性,然后叠加到一起就是一个视图。

iOS中绘图主要有以下两种方式:

1. iOS核心图形库:Core Graphics,缩写CG。主要通过核心图形库和UIKit进行封装,更贴近我们常操作的视图(UIView)和窗体(UIWindow)。Quartz 2D框架就是CG的一部分,是一个强大的二维图像绘制引擎。

2. OpenGL ES,经常用在游戏等需要对界面高频刷新和自由控制中,更贴近直接对屏幕的操控,可以作为视图机制的底层图形引擎。

下面用CGContextRef绘制了一个音频波形图,代码简单易读,先看一下效果图:

下面贴上代码:

ViewController:

#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
#import "ViewController.h"
#import "HWDrawView.h"
@interface ViewController ()
@property (nonatomic, strong) NSTimer *timer;
@property (nonatomic, strong) NSMutableArray *pointArray;
@property (nonatomic, strong) HWDrawView *drawView;
@property (nonatomic, weak) UIView *proView;
@property (nonatomic, weak) UIButton *startButton;
@end
@implementation ViewController
- (NSMutableArray *)pointArray
{
if (_pointArray == nil) {
_pointArray = [NSMutableArray array];
}
return _pointArray;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor blackColor];
//创建控件
[self creatControl];
}
- (void)creatControl
{
//动画视图
HWDrawView *view = [[HWDrawView alloc] initWithFrame:CGRectMake(30, 150, [UIScreen mainScreen].bounds.size.width - 60, 100)];
view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:view];
self.drawView = view;
//提示视图
UIView *proView = [[UIView alloc] initWithFrame:CGRectMake(30, 260, 20, 20)];
proView.backgroundColor = [UIColor greenColor];
proView.hidden = YES;
proView.layer.cornerRadius = 10;
proView.clipsToBounds = YES;
[self.view addSubview:proView];
self.proView = proView;
//开始按钮
UIButton *startBtn = [[UIButton alloc] initWithFrame:CGRectMake(([UIScreen mainScreen].bounds.size.width - 60) * 0.5 - 60, 300, 60, 60)];
startBtn.backgroundColor = [UIColor redColor];
[startBtn setTitle:@"开始" forState:UIControlStateNormal];
[startBtn addTarget:self action:@selector(startBtnOnClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:startBtn];
self.startButton = startBtn;
//停止按钮
UIButton *stopBtn = [[UIButton alloc] initWithFrame:CGRectMake(([UIScreen mainScreen].bounds.size.width - 60) * 0.5 + 60, 300, 60, 60)];
stopBtn.backgroundColor = [UIColor redColor];
[stopBtn setTitle:@"停止" forState:UIControlStateNormal];
[stopBtn addTarget:self action:@selector(stopBtnOnClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:stopBtn];
}
- (void)startBtnOnClick
{
self.startButton.enabled = NO;
self.proView.hidden = NO;
//添加定时器
_timer = [NSTimer scheduledTimerWithTimeInterval:.1f target:self selector:@selector(addPoint) userInfo:nil repeats:YES];
//分流定时器
[[NSRunLoop mainRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
}
- (void)addPoint
{
//随机点20~100
CGPoint point = CGPointMake(self.drawView.bounds.size.height, arc4random_uniform(80) + 20);
//插入到数组最前面(动画视图最右边),array添加CGPoint需要转换一下
[self.pointArray insertObject:[NSValue valueWithCGPoint:point] atIndex:0];
//传值,重绘视图
self.drawView.pointArray = self.pointArray;
}
- (void)stopBtnOnClick
{
self.startButton.enabled = YES;
self.proView.hidden = YES;
//移除定时器
[self removeTimer];
}
- (void)removeTimer
{
[_timer invalidate];
_timer = nil;
}
@end

HWDrawView:

#import <UIKit/UIKit.h>
@interface HWDrawView : UIView
@property (nonatomic, strong) NSArray *pointArray;
@end
#import "HWDrawView.h"
#define kLineWidth 2.f
@implementation HWDrawView
- (void)setPointArray:(NSArray *)pointArray
{
_pointArray = pointArray;
//调用该方法会重新加载drawRect方法
[self setNeedsDisplay];
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.clearsContextBeforeDrawing = YES;
}
return self;
}
- (void)drawRect:(CGRect)rect
{
if (self.pointArray.count == 0) {
return;
}
//获取上下文
CGContextRef ref = UIGraphicsGetCurrentContext();
//设置线条宽度
CGContextSetLineWidth(ref, kLineWidth);
//路径
CGContextBeginPath(ref);
//设置颜色
CGContextSetStrokeColorWithColor(ref, [UIColor orangeColor].CGColor);
for (int i = 0; i < self.pointArray.count; i++) {
CGPoint point = [[_pointArray objectAtIndex:i] CGPointValue];
//设置起点坐标
CGContextMoveToPoint(ref, self.bounds.size.width - i * kLineWidth * 2, self.bounds.size.height);
//设置下一个点坐标
CGContextAddLineToPoint(ref, self.bounds.size.width - i * kLineWidth * 2, self.bounds.size.height - point.y);
}
//渲染,连接起点和下一个坐标点
CGContextStrokePath(ref);
}
@end

 

如果想获得一个连续波形图,只需要把起点坐标设置在循环外面即可,效果如图:

贴上drawRect方法代码:

- (void)drawRect:(CGRect)rect
{
if (self.pointArray.count == 0) {
return;
}
//获取上下文
CGContextRef ref = UIGraphicsGetCurrentContext();
//设置线条宽度
CGContextSetLineWidth(ref, kLineWidth);
//路径
CGContextBeginPath(ref);
//设置颜色
CGContextSetStrokeColorWithColor(ref, [UIColor orangeColor].CGColor);
//设置起点坐标
CGContextMoveToPoint(ref, self.bounds.size.width, self.bounds.size.height);
for (int i = 0; i < self.pointArray.count; i++) {
CGPoint point = [[_pointArray objectAtIndex:i] CGPointValue];
//设置下一个点坐标
CGContextAddLineToPoint(ref, self.bounds.size.width - i * kLineWidth * 2, self.bounds.size.height - point.y);
}
//渲染,连接起点和下一个坐标点
CGContextStrokePath(ref);
}

 

猜你喜欢:iOS 进度条、加载、安装动画 —— HERO博客

人已赞赏
iOS文章

iOS 添加字体库

2020-2-23 9:18:48

iOS文章

iOS 搭建框架简述

2020-2-23 11:46:06

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索