使用BezierPath实现简单的画板
程序员文章站
2024-03-24 14:39:16
...
最近看了一下BezierPath,给娃们做一个简单的画板,啥话不说了,上代码!
Model:PathModel
#import <Foundation/Foundation.h>
#import "RWBezierPath.h"
@interface PathModel : NSObject
@property (nonatomic, assign)NSInteger pathWidth; // 线宽
@property (nonatomic, strong)NSArray *pathData; // 绘制数据
@property (nonatomic, strong)UIColor *pathUIColor; // 客户端使用的颜色
@property (nonatomic, strong)RWBezierPath *bezierPath;
@end
RWBezierPath:自定义的BezierPath,继承自UIBezierPath
#import <UIKit/UIKit.h>
@interface RWBezierPath : UIBezierPath
@property (nonatomic, strong) UIColor *lineColor;
@end
View:WhiteBoardView(这个是关键点)
.h
#import <UIKit/UIKit.h>
@interface WhiteBoardView : UIView
@property (nonatomic, strong) UIColor *lineColor;
@property (nonatomic, assign) NSInteger lineWidth;
// 清空
- (void)actionClean;
// 撤回
- (void)actionRecall;
@end
.m
#import "WhiteBoardView.h"
#import "PathModel.h"
#import "PointModel.h"
@interface WhiteBoardView ()
@property(nonatomic, strong) NSMutableArray *pathArray;//用来管理画板上所有的路径
@property(nonatomic, assign) CGPoint startPoint; // 划线的起点
@property(nonatomic, strong) NSMutableArray *pointArray; // 划线点的数组
@end
@implementation WhiteBoardView
- (NSMutableArray *)pathArray {
if (!_pathArray) {
_pathArray = [NSMutableArray array];
}
return _pathArray;
}
- (NSMutableArray *)pointArray {
if (!_pointArray) {
_pointArray = [NSMutableArray array];
}
return _pointArray;
}
- (void)setLineWidth:(NSInteger)lineWidth {
_lineWidth = lineWidth;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
// 获取触摸对象
UITouch *touch=[touches anyObject];
// 获取手指的位置
CGPoint point = [touch locationInView:touch.view];
self.startPoint = point;
//当手指按下的时候就创建一条路径
RWBezierPath *path=[RWBezierPath bezierPath];
//设置画笔宽度
[path setLineWidth:self.lineWidth];
//设置画笔颜色
[path setLineColor:self.lineColor];
//设置起点
[path moveToPoint:point];
PathModel *item = [[PathModel alloc] init];
item.pathWidth = path.lineWidth;
item.pathData = self.pointArray;
item.bezierPath = path;
item.pathUIColor = path.lineColor;
// 把每一次新创建的路径 添加到数组当中
[self.pathArray addObject:item];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
// 获取触摸对象
UITouch *touch=[touches anyObject];
// 获取手指的位置
CGPoint point = [touch locationInView:touch.view];
NSLog(@"point x= %f , y = %f",point.x,point.y);
// 连线的点
PathModel *item = [self.pathArray lastObject];
RWBezierPath *path = item.bezierPath;
[path addLineToPoint:point];
// 保存划线的点
PointModel *pointModel = [[PointModel alloc] init];
pointModel.startX = self.startPoint.x;
pointModel.startY = self.startPoint.y;
pointModel.endX = point.x;
pointModel.endY = point.y;
[self.pointArray addObject:pointModel];
[self setNeedsDisplay];
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSLog(@"触摸结束,准备发消息");
UITouch *touch=[touches anyObject];
CGPoint point = [touch locationInView:touch.view];
NSLog(@"point x= %f , y = %f",point.x,point.y);
PathModel *item = [self.pathArray lastObject];
RWBezierPath *path = item.bezierPath;
item.pathWidth = path.lineWidth;
item.pathData = self.pointArray;
item.pathUIColor = path.lineColor;
item.bezierPath = path;
[self.pointArray removeAllObjects];
[self setNeedsDisplay];
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
for (PathModel *pathItem in self.pathArray) {
[self setupBezierPath:pathItem.bezierPath];
}
}
- (void)setupBezierPath:(RWBezierPath *)bezierPath {
[bezierPath.lineColor set];
// 设置连接处的样式
[bezierPath setLineJoinStyle:kCGLineJoinRound];
// 设置头尾的样式
[bezierPath setLineCapStyle:kCGLineCapRound];
//渲染
[bezierPath stroke];
}
#pragma mark -当前用户的主动操作
// 清空
- (void)actionClean {
[self.pathArray removeAllObjects];
[self setNeedsDisplay];
}
// 撤回
- (void)actionRecall {
[self.pathArray removeLastObject];
[self setNeedsDisplay];
}
@end
使用:
//
// ViewController.m
// RitaBoard
//
// Created by 王红艳 on 2020/7/27.
// Copyright © 2020 王红艳. All rights reserved.
//
#import "ViewController.h"
#import "WhiteBoardView.h"
#import "RWControlButton.h"
#define kButtonWidth 40
#define marginTop 10
@interface ViewController ()
@property (nonatomic, strong)WhiteBoardView *boardView;
@property (nonatomic, strong)UIView *controlView;
@property (nonatomic, strong)UIView *toolView;
@property (nonatomic, strong)UISlider *sliderView;
@property (nonatomic, strong)NSMutableArray *colorArray;
@property (nonatomic, strong)UIColor *selectLineColor;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
self.controlView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 60)];
[self.view addSubview:self.controlView];
[self setupControlView];
self.boardView = [[WhiteBoardView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(self.controlView.frame), self.view.frame.size.width, self.view.frame.size.height - 120)];
self.boardView.backgroundColor = [UIColor whiteColor];
self.boardView.lineColor = [UIColor blackColor];
self.boardView.lineWidth = 5;
[self.view addSubview:self.boardView];
self.sliderView = [[UISlider alloc] initWithFrame:CGRectMake(20, self.view.frame.size.height - 100, 300, 30)];
self.sliderView.minimumValue = 5;
self.sliderView.maximumValue = 50;
[self.sliderView addTarget:self action:@selector(sliderDidTapped:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:self.sliderView];
self.toolView = [[UIView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(self.boardView.frame), self.view.frame.size.width,60)];
[self.view addSubview:self.toolView];
[self setupToolView];
}
- (void)sliderDidTapped:(UISlider *)sender {
self.boardView.lineWidth = sender.value;
}
- (void)setupControlView {
NSInteger marginLeft = (self.view.frame.size.width - kButtonWidth*4 - 25*3)/2;
RWControlButton *drawLineButton = [self createButton:CGRectMake(marginLeft, marginTop, kButtonWidth, kButtonWidth)
imageName:@"bai_ban_hua_bi"
selectImageName:@"bai_ban_hua_bi_xuan_zhong"
tag:0];
[self.controlView addSubview:drawLineButton];
RWControlButton *eraserButton = [self createButton:CGRectMake(CGRectGetMaxX(drawLineButton.frame) + 25, marginTop, kButtonWidth, kButtonWidth)
imageName:@"bai_ban_xiang_pi"
selectImageName:@"bai_ban_xiang_pi_xuan_zhong"
tag:1];
[self.controlView addSubview:eraserButton];
RWControlButton *recallButton = [self createButton:CGRectMake(CGRectGetMaxX(eraserButton.frame) + 25, marginTop, kButtonWidth, kButtonWidth)
imageName:@"bai_ban_che_xiao"
selectImageName:@"bai_ban_che_xiao"
tag:2];
[self.controlView addSubview:recallButton];
RWControlButton *cleanButton = [self createButton:CGRectMake(CGRectGetMaxX(recallButton.frame) + 25, marginTop, kButtonWidth, kButtonWidth)
imageName:@"bai_ban_qing_chu"
selectImageName:@"bai_ban_qing_chu"
tag:3];
[self.controlView addSubview:cleanButton];
}
- (RWControlButton *)createButton:(CGRect)frame imageName:(NSString *)imageName selectImageName:(NSString *)selectImageName tag:(NSInteger)tag {
RWControlButton *button = [[RWControlButton alloc] initWithFrame:frame imageName:imageName selectedImageName:selectImageName];
button.tag = tag;
[button addTarget:self action:@selector(actionSetColorDidTapped:) forControlEvents:UIControlEventTouchUpInside];
return button;
}
- (void)actionSetColorDidTapped:(UIButton *)sender {
if (sender.tag == 0) {
self.boardView.lineColor = self.selectLineColor;
} else if (sender.tag == 1) {
self.boardView.lineColor = [UIColor whiteColor];
} else if (sender.tag == 2) {
[self.boardView actionRecall];
} else if (sender.tag == 3) {
[self.boardView actionClean];
}
}
- (void)setupToolView {
self.colorArray = [NSMutableArray arrayWithObjects:
[UIColor colorWithRed:255.0/255.0 green:0/255.0 blue:0/255.0 alpha:1.0],
[UIColor colorWithRed:255.0/255.0 green:51.0/255.0 blue:0/255.0 alpha:1.0],
[UIColor colorWithRed:255.0/255.0 green:102.0/255.0 blue:0/255.0 alpha:1.0],
[UIColor colorWithRed:255.0/255.0 green:153.0/255.0 blue:0/255.0 alpha:1.0],
[UIColor colorWithRed:255.0/255.0 green:255.0/255.0 blue:0/255.0 alpha:1.0],
[UIColor colorWithRed:153.0/255.0 green:255.0/255.0 blue:0/255.0 alpha:1.0],
[UIColor colorWithRed:0/255.0 green:255.0/255.0 blue:0/255.0 alpha:1.0],
[UIColor colorWithRed:0/255.0 green:255.0/255.0 blue:255.0/255.0 alpha:1.0],
[UIColor colorWithRed:0/255.0 green:0/255.0 blue:255.0/255.0 alpha:1.0],
[UIColor colorWithRed:102.0/255.0 green:0/255.0 blue:255.0/255.0 alpha:1.0],
[UIColor colorWithRed:255.0/255.0 green:0/255.0 blue:255.0/255.0 alpha:1.0],
[UIColor colorWithRed:255.0/255.0 green:0/255.0 blue:102.0/255.0 alpha:1.0],
[UIColor colorWithRed:136.0/255.0 green:136.0/255.0 blue:136.0/255.0 alpha:1.0],
[UIColor colorWithRed:132.0/255.0 green:90.0/255.0 blue:51.0/255.0 alpha:1.0],
[UIColor blackColor],nil];
NSInteger marginLeft = (self.view.frame.size.width - 35*self.colorArray.count - 15*(self.colorArray.count - 1))/2;
NSInteger tempMarginTop = 10;
for (int i = 0; i < self.colorArray.count; i ++) {
CGRect buttonF = CGRectMake(marginLeft + 15*i + 35*i, tempMarginTop, 35, 35);
UIColor *lineColor = [self.colorArray objectAtIndex:i];
UIButton *colorButton = [[UIButton alloc] initWithFrame:buttonF];
[colorButton setBackgroundColor:lineColor];
colorButton.tag = i;
[self.toolView addSubview:colorButton];
[colorButton addTarget:self action:@selector(actionSetLineColor:) forControlEvents:UIControlEventTouchUpInside];
}
}
- (void)actionSetLineColor:(UIButton *)sender {
UIColor *lineColor = [self.colorArray objectAtIndex:sender.tag];
self.boardView.lineColor = lineColor;
self.selectLineColor = lineColor;
}
@end
在制作demo的时候 我自己简单写了一个工具条,用来选择的 可以参考一下:
RWControlButton
//
// RWControlButton.h
// RitaBoard
//
// Created by 王红艳 on 2020/7/27.
// Copyright © 2020 王红艳. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface RWControlButton : UIButton
- (instancetype)initWithFrame:(CGRect)frame imageName:(NSString *)imageName selectedImageName:(NSString *)selectedImageName;
@end
//
// RWControlButton.m
// RitaBoard
//
// Created by 王红艳 on 2020/7/27.
// Copyright © 2020 王红艳. All rights reserved.
//
#import "RWControlButton.h"
#define kImageMargin 6
@interface RWControlButton ()
@property (nonatomic,strong)UIImageView *backImageView;
@property (nonatomic,strong)NSString *imageName;
@property (nonatomic,strong)NSString *selectedImageName;
@end
@implementation RWControlButton
- (instancetype)initWithFrame:(CGRect)frame imageName:(NSString *)imageName selectedImageName:(NSString *)selectedImageName {
self = [super initWithFrame:frame];
if (self) {
self.layer.masksToBounds = YES;
self.layer.cornerRadius = frame.size.width/2;
self.imageName = imageName;
self.selectedImageName = selectedImageName;
self.backImageView = [[UIImageView alloc] initWithFrame:CGRectMake(kImageMargin, kImageMargin, frame.size.width - kImageMargin*2, frame.size.height - kImageMargin * 2)];
self.backImageView.image = [UIImage imageNamed:imageName];
[self addSubview:self.backImageView];
}
return self;
}
- (void)setSelected:(BOOL)selected {
if (selected == YES) {
self.backImageView.image = [UIImage imageNamed:self.selectedImageName];
self.backgroundColor = [UIColor colorWithRed:243/255.0 green:243/255.0 blue:245/255.0 alpha:1.0];
} else {
self.backImageView.image = [UIImage imageNamed:self.imageName];
self.backgroundColor = [UIColor whiteColor];
}
}
@end
看一下效果图:
上一篇: 如何更好地学习和练习Leetcode
下一篇: 套接字socket使用(udp篇)上