CAShapeLayer画板
2016-08-30 本文已影响137人
Acthink
参考:CAShapeLayer - 绘图板
由于参考的文章代码的线条是写死的,所有对于画板的需求来说,还是不太好用,所以自己写了个Demo
直接上代码了:
<code>
@interface ViewController ()
@property (nonatomic, strong, nullable) NSMutableArray * drawPaths;
@property (nonatomic, strong, nullable) NSMutableArray * drawLayers;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton * clearBtn = [[UIButton alloc]
initWithFrame:CGRectMake(self.view.bounds.size.width - 100, 44, 100, 50)];
clearBtn.backgroundColor = [UIColor grayColor];
[clearBtn setTitleColor:[UIColor greenColor] forState:UIControlStateNormal];
[clearBtn setTitle:@"clear" forState:UIControlStateNormal];
clearBtn.tag = 1;
[clearBtn addTarget:self action:@selector(backOrClear:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview: clearBtn];
UIButton * backBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 44, 100, 50)];
backBtn.backgroundColor = [UIColor grayColor];
[backBtn setTitleColor:[UIColor greenColor] forState:UIControlStateNormal];
[backBtn setTitle:@"back" forState:UIControlStateNormal];backBtn.tag = 2;
[backBtn addTarget:self action:@selector(backOrClear:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview: backBtn];
}
- (void)backOrClear:(UIButton *)sender{
switch (sender.tag) {
case 1:{
for (CAShapeLayer * layer in self.drawLayers) {
[layer removeFromSuperlayer];
}
self.drawLayers = nil;
[self.drawPaths removeAllObjects];
}
break;
default:{
CAShapeLayer * layer = self.drawLayers.lastObject;
[layer removeFromSuperlayer];
[self.drawLayers removeLastObject];
}
break;
}
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[super touchesBegan:touches withEvent:event];
UIBezierPath * path = [UIBezierPath bezierPath];
[path moveToPoint:[[touches anyObject] locationInView:self.view]];
CAShapeLayer *layer = [CAShapeLayer layer];
layer.backgroundColor = [UIColor clearColor].CGColor;
layer.frame = self.view.bounds;
layer.path = path.CGPath;
layer.lineWidth = 3.0f;
layer.strokeColor = [UIColor redColor].CGColor;
layer.miterLimit = 2.;
layer.lineDashPhase = 10;
layer.lineDashPattern = @[@1,@0];
layer.fillColor = [UIColor clearColor].CGColor;
layer.fillRule = kCAFillRuleEvenOdd;
layer.lineCap = kCALineCapRound;
layer.lineJoin = kCALineJoinRound; // 结合 CABasicAnimation 可以变成 动画绘制 // 将layer添加进图层
[self.view.layer addSublayer:layer];
[self.drawPaths addObject:path];
[self.drawLayers addObject:layer];
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[super touchesMoved:touches withEvent:event];
UIBezierPath * path = self.drawPaths.lastObject;
CAShapeLayer * layer = self.drawLayers.lastObject;
[path addLineToPoint:[[touches anyObject] locationInView:self.view]];
layer.path = path.CGPath;
}
- (NSMutableArray *)drawPaths{
if (_drawPaths == nil) {
_drawPaths = [NSMutableArray array];
}
return _drawPaths;
}
- (NSMutableArray *)drawLayers{
if (_drawLayers == nil) {
_drawLayers = [NSMutableArray array];
}
return _drawLayers;
}
</code>
有人可能会问了,这么写,会不会有问题,为什么不用一个UIBezierPath曲线画,我是这样考虑的:
1.一条曲线渲染速度太慢,画的越多,渲染的速度越慢.会造成延时渲染的效果.这个是我跳入的坑,刚爬出来.
2.对于画板的需求来说,回撤的可能是非常大的.一条曲线不容易操作
对于一条曲线来说,如果渲染慢的话,还是可以解决的,不过要调用,layer的-setNeedsDisplayInRect:方法对touch附近的区域进行渲染,这个继续研究
有不明白的欢迎下载Demo