您的位置:首页 > 移动开发 > IOS开发

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

2015-12-24 17:55 501 查看
简单说一下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 "HWDrawVie
4000
w.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博客
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息