iOS绘图模仿扁平笔尖

时间:2016-03-21 13:00:27

标签: ios objective-c drawing core-graphics uibezierpath

我正在创建一个绘图应用程序,我想模拟一个扁平的笔尖。令人惊讶的是,它变成了相当困难的任务这是我的解决方案:

- (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"的应用程序。它是关于阿拉伯语的,您应该点击主屏幕上的第二个按钮打开绘画。这是我想要的完美范例。

1 个答案:

答案 0 :(得分:2)

这是一个非常常见的问题。

问题在于

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 documentation,您会看到Apple说:

  

必须在主线程上对应用程序的用户界面进行操作。因此,您应该始终从应用程序主线程中运行的代码调用UIView类的方法。

因此你应该这样做

self.drawingImageView.image = UIGraphicsGetImageFromCurrentImageContext()

代替。

关于您使用UIBezierPath的评论 - 我没有看到此更改带给您的任何明显优势 - 自己绘制路径与使用{{1}一样直接绘图方法。

但是,如果您仍然想要,您当然可以使用UIBezierPath - 您需要执行以下操作:

UIBezierPath