Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
iOS绘图模拟平头笔_Ios_Objective C_Drawing_Core Graphics_Uibezierpath - Fatal编程技术网

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很乐意帮助:)