Ran*_*jit 2 core-graphics objective-c uikit ios uibezierpath
我正在做一个绘图应用程序,我正在尝试平滑我用手指绘制的线.为此我使用"quadCurveToPoint"功能.但是,我没有做对.
以下是我的代码:
- (void) drawRect:(CGRect)rect
{
[path stroke];
}
- (id) initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
self.multipleTouchEnabled = NO;
path = [UIBezierPath bezierPath];
path.lineWidth = IS_IPAD? 2.0f : 1.0f;
return self;
}
- (void) touchesBegan:(NSSet *) touches withEvent:(UIEvent *) event
{
UITouch *touch = [touches anyObject];
m_previousPoint1 = [touch locationInView:self];
m_previousPoint2 = [touch locationInView:self];
m_currentPoint = [touch locationInView:self];
}
//Find the midpoint
CGPoint midPoint(CGPoint p1, CGPoint p2)
{
return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5);
}
- (void) touchesMoved:(NSSet *) touches withEvent:(UIEvent *) event
{
UITouch *touch = [touches anyObject];
m_previousPoint2 = m_previousPoint1;
m_previousPoint1 = m_currentPoint;
m_currentPoint = [touch locationInView:self];
CGPoint mid1 = midPoint(m_previousPoint1, m_previousPoint2);
CGPoint mid2 = midPoint(m_currentPoint, m_previousPoint1);
[path setFlatness:1.0f];
[path setLineCapStyle:kCGLineCapRound];
[path setLineJoinStyle:kCGLineJoinRound];
[path moveToPoint:m_previousPoint1];
[path addLineToPoint:mid1];
[path addQuadCurveToPoint:mid2 controlPoint:m_currentPoint];
[self setNeedsDisplay];
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
}
Run Code Online (Sandbox Code Playgroud)
当我用手指画画时,我正在设置如下所示的路径:

我不明白我错过了什么.所以我在这方面需要帮助.
编辑:图片发布到以下答案.

谢谢Ranjit
你的代码看起来不错.但要解决您提到的问题,请将当前代码更改为以下内容:
更改:
[path moveToPoint:m_previousPoint1];
[path addLineToPoint:mid1];
Run Code Online (Sandbox Code Playgroud)
至:
[path moveToPoint:mid1];
[path addLineToPoint:m_previousPoint1];
Run Code Online (Sandbox Code Playgroud)
并改变这个:
[path addQuadCurveToPoint:mid2 controlPoint:m_currentPoint];
Run Code Online (Sandbox Code Playgroud)
至:
[path addQuadCurveToPoint:m_currentPoint controlPoint:mid2];
Run Code Online (Sandbox Code Playgroud)
测试.
附录(WWDC算法):
背景:
据WWDC说,这个想法是这样的:
1.)我们使用中点作为起点和终点,而不是使用当前点.
2.)因此,我们使用实际触摸点作为控制点.
您的代码的分析/更正:
所以这里是我使用WWDC中引入的思想的简化版代码.
你明白了.几乎.鉴于上述情况,我们需要对您的代码touchesMoved进行以下更改:
1.)
如果我们使用中点作为
ToPoint值,我们需要注意第一种情况,当只有一个当前点时,因为只有一个当前点,我们无法从中得到一个中点 - 我们需要2个点.
因此,我们需要首先"读取"当前点之后的一个点以计算中点.以下是这样的:
UITouch *touch = [touches anyObject];
m_previousPoint1 = m_currentPoint;
m_currentPoint = [touch locationInView:self];
mid1 = midPoint(m_currentPoint, m_previousPoint1);
if(counter == 1)
{
[path moveToPoint:m_currentPoint];
[path addLineToPoint:mid1];
[self setNeedsDisplay];
}
Run Code Online (Sandbox Code Playgroud)
变量计数器最初设置为0.因此,当计数器为1时,直到第二次传递才会被绘制.当它是时,我们将有2个点来计算中点.
然后是其余的接触:
2.)
一旦第一个案例得到处理,我们就会前进到曲线的其余部分,并适当地推导出我们连接段的点:
else if(counter > 1)
{
[path addQuadCurveToPoint:mid1 controlPoint:m_previousPoint1];
[self setNeedsDisplay];
}
counter++;
Run Code Online (Sandbox Code Playgroud)
这是上面else if第一个之后的权利if.我们只在处理第一个案例时进入这里,为此我使用一个简单的计数器并在每次touchesMoved调用时递增它.
这里发生的是我们从前一个中间点连接到mid1使用前一个点作为控制点.那么,目前的情况呢?我们正在使用它直到下一次通过.
3.)最后,我们关注曲线的最后一段
touchesEnded:
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[path addLineToPoint:[[touches anyObject] locationInView:self]];
[self setNeedsDisplay];
}
Run Code Online (Sandbox Code Playgroud)
这只是从中点到最后一点画一条线.
最后touchesBegan,我设置了counter = 0;,所以下一条曲线将再次开始上述过程.
我使用模拟器和设备测试了上面的内容,这是一个屏幕截图:

以下是完整的来源:
- (void) touchesBegan:(NSSet *) touches withEvent:(UIEvent *) event
{
UITouch *touch = [touches anyObject];
counter = 0;
m_previousPoint1 = [touch locationInView:self];
m_currentPoint = [touch locationInView:self];
}
//Find the midpoint
CGPoint midPoint(CGPoint p1, CGPoint p2)
{
return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5);
}
- (void) touchesMoved:(NSSet *) touches withEvent:(UIEvent *) event
{
UITouch *touch = [touches anyObject];
m_previousPoint1 = m_currentPoint;
m_currentPoint = [touch locationInView:self];
mid1 = midPoint(m_currentPoint, m_previousPoint1);
[path setFlatness:1.0f];
[path setLineCapStyle:kCGLineCapRound];
[path setLineJoinStyle:kCGLineJoinRound];
if(counter == 1)
{
[path moveToPoint:m_currentPoint];
[path addLineToPoint:mid1];
[self setNeedsDisplay];
}
else if(counter > 1)
{
[path addQuadCurveToPoint:mid1 controlPoint:m_previousPoint1];
[self setNeedsDisplay];
}
counter++;
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[path addLineToPoint:[[touches anyObject] locationInView:self]];
[self setNeedsDisplay];
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2292 次 |
| 最近记录: |