iOS绘图模拟平头笔
我正在创建一个绘图应用程序,我想模拟一支平头笔。令人惊讶的是,这变成了一项相当困难的任务。这是我的解决方案:iOS绘图模拟平头笔,ios,objective-c,drawing,core-graphics,uibezierpath,Ios,Objective C,Drawing,Core Graphics,Uibezierpath,我正在创建一个绘图应用程序,我想模拟一支平头笔。令人惊讶的是,这变成了一项相当困难的任务。这是我的解决方案: - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint currentPoint = [touch locationInView:self.drawingImageView]; currentP
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.drawingImageView];
currentPoint = CGPointMake(roundf(currentPoint.x), roundf(currentPoint.y));
UIGraphicsBeginImageContext(self.drawingImageView.frame.size);
[self.drawingImageView.image drawInRect:CGRectMake(0, 0, self.drawingImageView.frame.size.width, self.drawingImageView.frame.size.height)];
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextMoveToPoint (ctx, lastPoint.x + 8.f, lastPoint.y - 8.f);
CGContextAddLineToPoint(ctx, currentPoint.x + 8.f, currentPoint.y - 8.f);
CGContextAddLineToPoint(ctx, currentPoint.x - 8.f, currentPoint.y + 8.f);
CGContextAddLineToPoint(ctx, lastPoint.x - 8.f, lastPoint.y + 8.f);
CGContextAddLineToPoint(ctx, lastPoint.x + 8.f, lastPoint.y - 8.f);
CGContextClosePath(ctx);
CGContextSetRGBFillColor(ctx, 0, 0, 0, 1);
CGContextDrawPath(ctx, kCGPathFillStroke);
[self.drawingImageView performSelectorInBackground:@selector(setImage:) withObject:UIGraphicsGetImageFromCurrentImageContext()];
UIGraphicsEndImageContext();
lastPoint = currentPoint;
}
这就是它的样子:
如您所见,边缘并不平滑。我想改为使用UIBezierPath
,但我没有找到使用UIBezierPath
实现平头笔效果的方法。也许有一些方法可以改进我的代码或任何其他方法(也许UIBezierPath
)
我能找到的唯一一个具有这种绘画风格的应用程序是名为“Khattat”的应用程序。它是阿拉伯语的,你应该点击主屏幕上的第二个按钮打开绘画。这是我想要的一个完美的例子 这是一个相当普遍的问题。
问题出在线路上
UIGraphicsBeginImageContext(self.drawingImageView.frame.size);
这样做的目的是创建一个新的透明图像上下文,其大小与图像视图相同,但比例为1.0
。由于这种比例-在其中完成的任何图形都必须进行上采样,才能在2x或3x显示器上显示-因此您的图形会变得模糊
解决方法非常简单。你可以用
UIGraphicsBeginImageContextWithOptions(drawingImageView.frame.size, NO, 0.0);
通过将0.0
传递到scale参数中,Core Graphics将自动检测屏幕的比例,并将上下文的比例设置为匹配。因此,您在其中绘制的任何图形都将以正确的分辨率绘制
还有,我刚注意到那条线
[self.drawingImageView performSelectorInBackground:@selector(setImage:) withObject:UIGraphicsGetImageFromCurrentImageContext()];
这听起来不是个好主意。如果你看一下,你会看到苹果说:
对应用程序用户界面的操作必须在主线程上进行。因此,您应该始终从应用程序主线程中运行的代码调用UIView类的方法
所以你应该做什么
self.drawingImageView.image = UIGraphicsGetImageFromCurrentImageContext()
相反
关于您关于使用
UIBezierPath
-我看不出这一更改会给您带来任何明显的好处-自己将路径绘制到上下文中与使用UIBezierPath
方法进行绘制一样直接
但是,如果您仍然想要,您当然可以使用UIBezierPath
来代替-您需要执行以下操作:
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self];
currentPoint = CGPointMake(roundf(currentPoint.x), roundf(currentPoint.y));
UIGraphicsBeginImageContextWithOptions(drawingImageView.frame.size, NO, 0.0);
[drawingImageView.image drawInRect:CGRectMake(0, 0, drawingImageView.frame.size.width, drawingImageView.frame.size.height)];
UIBezierPath* path = [UIBezierPath bezierPath];
[path moveToPoint:(CGPoint){lastPoint.x + 8.f, lastPoint.y - 8.f}];
[path addLineToPoint:(CGPoint){currentPoint.x + 8.f, currentPoint.y - 8.f}];
[path addLineToPoint:(CGPoint){currentPoint.x - 8.f, currentPoint.y + 8.f}];
[path addLineToPoint:(CGPoint){lastPoint.x - 8.f, lastPoint.y + 8.f}];
[path addLineToPoint:(CGPoint){lastPoint.x + 8.f, lastPoint.y - 8.f}];
[[UIColor blackColor] set];
[path fill];
drawingImageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
lastPoint = currentPoint;
谢谢,这很有帮助。使用
UIBezierPath
或CGContext
没有区别,您是对的。@tagirkaZ很乐意帮助:)